├── .gitignore
├── LICENSE
├── Makefile
├── README.md
├── SECURITY.md
├── VisualStudio
├── frodo.sln
├── frodo.vcxproj
├── frodo.vcxproj.filters
├── test_kex
│ ├── test_kex.vcxproj
│ └── test_kex.vcxproj.filters
└── test_rand
│ ├── test_rand.vcxproj
│ └── test_rand.vcxproj.filters
├── src
├── aes
│ ├── aes.c
│ ├── aes.h
│ ├── aes_c.c
│ ├── aes_local.h
│ ├── aes_ni.c
│ └── test_aes.c
├── frodo.h
├── frodo_macrify.h
├── kex.c
├── kex.h
├── kex_lwe_frodo.c
├── kex_lwe_frodo.h
├── kex_lwe_frodo_macrify.c
├── lwe.c
├── lwe_macrify.c
├── lwe_macrify_reference.c
├── lwe_noise.c
├── random
│ ├── rand.c
│ ├── rand.h
│ ├── rand_urandom_aesctr
│ │ ├── rand_urandom_aesctr.c
│ │ └── rand_urandom_aesctr.h
│ └── test_rand.c
└── sha3
│ ├── fips202.c
│ ├── fips202.h
│ ├── fips202x4.c
│ ├── fips202x4.h
│ └── keccak4x
│ ├── KeccakP-1600-times4-SIMD256.c
│ ├── KeccakP-1600-times4-SnP.h
│ ├── KeccakP-1600-unrolling.macros
│ ├── KeccakP-1600-unrolling.txt
│ ├── SIMD256-config.h
│ ├── align.h
│ └── brg_endian.h
└── tests
├── ds_benchmark.h
└── test_kex.c
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.suo
8 | *.user
9 | *.userosscache
10 | *.sln.docstates
11 |
12 | # User-specific files (MonoDevelop/Xamarin Studio)
13 | *.userprefs
14 |
15 | # Build results
16 | [Dd]ebug/
17 | [Dd]ebugPublic/
18 | [Rr]elease/
19 | [Rr]eleases/
20 | x64/
21 | x86/
22 | bld/
23 | [Bb]in/
24 | [Oo]bj/
25 | [Ll]og/
26 |
27 | # Visual Studio 2015 cache/options directory
28 | .vs/
29 | # Uncomment if you have tasks that create the project's static files in wwwroot
30 | #wwwroot/
31 |
32 | # MSTest test Results
33 | [Tt]est[Rr]esult*/
34 | [Bb]uild[Ll]og.*
35 |
36 | # NUNIT
37 | *.VisualState.xml
38 | TestResult.xml
39 |
40 | # Build Results of an ATL Project
41 | [Dd]ebugPS/
42 | [Rr]eleasePS/
43 | dlldata.c
44 |
45 | # .NET Core
46 | project.lock.json
47 | project.fragment.lock.json
48 | artifacts/
49 | **/Properties/launchSettings.json
50 |
51 | *_i.c
52 | *_p.c
53 | *_i.h
54 | *.ilk
55 | *.meta
56 | *.obj
57 | *.pch
58 | *.pdb
59 | *.pgc
60 | *.pgd
61 | *.rsp
62 | *.sbr
63 | *.tlb
64 | *.tli
65 | *.tlh
66 | *.tmp
67 | *.tmp_proj
68 | *.log
69 | *.vspscc
70 | *.vssscc
71 | .builds
72 | *.pidb
73 | *.svclog
74 | *.scc
75 |
76 | # Chutzpah Test files
77 | _Chutzpah*
78 |
79 | # Visual C++ cache files
80 | ipch/
81 | *.aps
82 | *.ncb
83 | *.opendb
84 | *.opensdf
85 | *.sdf
86 | *.cachefile
87 | *.VC.db
88 | *.VC.VC.opendb
89 |
90 | # Visual Studio profiler
91 | *.psess
92 | *.vsp
93 | *.vspx
94 | *.sap
95 |
96 | # TFS 2012 Local Workspace
97 | $tf/
98 |
99 | # Guidance Automation Toolkit
100 | *.gpState
101 |
102 | # ReSharper is a .NET coding add-in
103 | _ReSharper*/
104 | *.[Rr]e[Ss]harper
105 | *.DotSettings.user
106 |
107 | # JustCode is a .NET coding add-in
108 | .JustCode
109 |
110 | # TeamCity is a build add-in
111 | _TeamCity*
112 |
113 | # DotCover is a Code Coverage Tool
114 | *.dotCover
115 |
116 | # Visual Studio code coverage results
117 | *.coverage
118 | *.coveragexml
119 |
120 | # NCrunch
121 | _NCrunch_*
122 | .*crunch*.local.xml
123 | nCrunchTemp_*
124 |
125 | # MightyMoose
126 | *.mm.*
127 | AutoTest.Net/
128 |
129 | # Web workbench (sass)
130 | .sass-cache/
131 |
132 | # Installshield output folder
133 | [Ee]xpress/
134 |
135 | # DocProject is a documentation generator add-in
136 | DocProject/buildhelp/
137 | DocProject/Help/*.HxT
138 | DocProject/Help/*.HxC
139 | DocProject/Help/*.hhc
140 | DocProject/Help/*.hhk
141 | DocProject/Help/*.hhp
142 | DocProject/Help/Html2
143 | DocProject/Help/html
144 |
145 | # Click-Once directory
146 | publish/
147 |
148 | # Publish Web Output
149 | *.[Pp]ublish.xml
150 | *.azurePubxml
151 | # TODO: Comment the next line if you want to checkin your web deploy settings
152 | # but database connection strings (with potential passwords) will be unencrypted
153 | *.pubxml
154 | *.publishproj
155 |
156 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
157 | # checkin your Azure Web App publish settings, but sensitive information contained
158 | # in these scripts will be unencrypted
159 | PublishScripts/
160 |
161 | # NuGet Packages
162 | *.nupkg
163 | # The packages folder can be ignored because of Package Restore
164 | **/packages/*
165 | # except build/, which is used as an MSBuild target.
166 | !**/packages/build/
167 | # Uncomment if necessary however generally it will be regenerated when needed
168 | #!**/packages/repositories.config
169 | # NuGet v3's project.json files produces more ignorable files
170 | *.nuget.props
171 | *.nuget.targets
172 |
173 | # Microsoft Azure Build Output
174 | csx/
175 | *.build.csdef
176 |
177 | # Microsoft Azure Emulator
178 | ecf/
179 | rcf/
180 |
181 | # Windows Store app package directories and files
182 | AppPackages/
183 | BundleArtifacts/
184 | Package.StoreAssociation.xml
185 | _pkginfo.txt
186 |
187 | # Visual Studio cache files
188 | # files ending in .cache can be ignored
189 | *.[Cc]ache
190 | # but keep track of directories ending in .cache
191 | !*.[Cc]ache/
192 |
193 | # Others
194 | ClientBin/
195 | ~$*
196 | *~
197 | *.dbmdl
198 | *.dbproj.schemaview
199 | *.jfm
200 | *.pfx
201 | *.publishsettings
202 | orleans.codegen.cs
203 |
204 | # Since there are multiple workflows, uncomment next line to ignore bower_components
205 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
206 | #bower_components/
207 |
208 | # RIA/Silverlight projects
209 | Generated_Code/
210 |
211 | # Backup & report files from converting an old project file
212 | # to a newer Visual Studio version. Backup files are not needed,
213 | # because we have git ;-)
214 | _UpgradeReport_Files/
215 | Backup*/
216 | UpgradeLog*.XML
217 | UpgradeLog*.htm
218 |
219 | # SQL Server files
220 | *.mdf
221 | *.ldf
222 | *.ndf
223 |
224 | # Business Intelligence projects
225 | *.rdl.data
226 | *.bim.layout
227 | *.bim_*.settings
228 |
229 | # Microsoft Fakes
230 | FakesAssemblies/
231 |
232 | # GhostDoc plugin setting file
233 | *.GhostDoc.xml
234 |
235 | # Node.js Tools for Visual Studio
236 | .ntvs_analysis.dat
237 | node_modules/
238 |
239 | # Typescript v1 declaration files
240 | typings/
241 |
242 | # Visual Studio 6 build log
243 | *.plg
244 |
245 | # Visual Studio 6 workspace options file
246 | *.opt
247 |
248 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
249 | *.vbw
250 |
251 | # Visual Studio LightSwitch build output
252 | **/*.HTMLClient/GeneratedArtifacts
253 | **/*.DesktopClient/GeneratedArtifacts
254 | **/*.DesktopClient/ModelManifest.xml
255 | **/*.Server/GeneratedArtifacts
256 | **/*.Server/ModelManifest.xml
257 | _Pvt_Extensions
258 |
259 | # Paket dependency manager
260 | .paket/paket.exe
261 | paket-files/
262 |
263 | # FAKE - F# Make
264 | .fake/
265 |
266 | # JetBrains Rider
267 | .idea/
268 | *.sln.iml
269 |
270 | # CodeRush
271 | .cr/
272 |
273 | # Python Tools for Visual Studio (PTVS)
274 | __pycache__/
275 | *.pyc
276 |
277 | # Cake - Uncomment if you are using it
278 | # tools/**
279 | # !tools/packages.config
280 |
281 | # Telerik's JustMock configuration file
282 | *.jmconfig
283 |
284 | # BizTalk build output
285 | *.btp.cs
286 | *.btm.cs
287 | *.odx.cs
288 | *.xsd.cs
289 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) Microsoft Corporation. All rights reserved.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE
22 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | #### Makefile for compilation on Linux ####
2 |
3 | CC=gcc
4 | ifeq "$(CC)" "gcc"
5 | COMPILER=gcc
6 | else ifeq "$(CC)" "clang"
7 | COMPILER=clang
8 | endif
9 |
10 | ARCH=x64
11 | ifeq "$(ARCH)" "x64"
12 | ARCHITECTURE=_AMD64_
13 | else ifeq "$(ARCH)" "x86"
14 | ARCHITECTURE=_X86_
15 | else ifeq "$(ARCH)" "ARM"
16 | ARCHITECTURE=_ARM_
17 | endif
18 |
19 | AR=ar rcs
20 | RANLIB=ranlib
21 | LN=ln -s
22 |
23 | CFLAGS= -O3 -std=gnu11 -Wall -Wextra -march=native -DLINUX -D $(ARCHITECTURE)
24 | LDFLAGS=-lm
25 | INCLUDES=-Iinclude
26 |
27 | ifeq "$(ARCH)" "x64"
28 | ifeq "$(USE_AVX2)" "FALSE"
29 | else
30 | CFLAGS += -DAVX2
31 | endif
32 | ifeq "$(AES_NI)" "FALSE"
33 | CFLAGS += -DAES_DISABLE_NI
34 | else
35 | CFLAGS += -maes -msse2 -DAES_ENABLE_NI
36 | endif
37 | else
38 | CFLAGS += -DAES_DISABLE_NI
39 | endif
40 |
41 | ifeq "$(USE_REFERENCE)" "TRUE"
42 | CFLAGS += -DREFERENCE
43 | endif
44 |
45 | .PHONY: all check clean prettyprint
46 |
47 | all: links lib tests
48 |
49 | objs/%.o: src/%.c
50 | @mkdir -p $(@D)
51 | $(CC) -c $(CFLAGS) $(INCLUDES) $< -o $@
52 |
53 | links:
54 | rm -rf include/frodo
55 | mkdir -p include/frodo
56 | $(LN) ../../src/aes/aes.h include/frodo
57 | $(LN) ../../src/frodo.h include/frodo
58 | $(LN) ../../src/frodo_macrify.h include/frodo
59 | $(LN) ../../src/kex.h include/frodo
60 | $(LN) ../../src/kex_lwe_frodo.h include/frodo
61 | $(LN) ../../src/random/rand.h include/frodo
62 | $(LN) ../../src/random/rand_urandom_aesctr/rand_urandom_aesctr.h include/frodo
63 | $(LN) ../../src/sha3/fips202.h include/frodo
64 | $(LN) ../../src/sha3/fips202x4.h include/frodo
65 |
66 | # RAND_URANDOM_AESCTR
67 | RAND_URANDOM_AESCTR_OBJS := $(addprefix objs/random/rand_urandom_aesctr/, rand_urandom_aesctr.o)
68 | $(RAND_URANDOM_AESCTR_OBJS): src/random/rand_urandom_aesctr/rand_urandom_aesctr.h
69 |
70 | # RAND
71 | objs/random/rand.o: src/random/rand.h
72 |
73 | # KEX_LWE_FRODO
74 | KEX_LWE_FRODO_OBJS := $(addprefix objs/, lwe.o kex_lwe_frodo.o lwe_noise.o)
75 | KEX_LWE_FRODO_HEADERS := $(addprefix src/, kex_lwe_frodo.h frodo_macrify.h)
76 | $(KEX_LWE_FRODO_OBJS): $(KEX_LWE_FRODO_HEADERS)
77 |
78 | # AES
79 | AES_OBJS := $(addprefix objs/aes/, aes.o aes_c.o aes_ni.o)
80 | AES_HEADERS := $(addprefix src/aes/, aes.h)
81 | $(AES_OBJS): $(AES_HEADERS)
82 |
83 | # SHAKE
84 | SHAKE_OBJS := $(addprefix objs/sha3/, fips202.o)
85 | SHAKE_HEADERS := $(addprefix src/sha3/, fips202.h)
86 | $(SHAKE_OBJS): $(SHAKE_HEADERS)
87 |
88 | # SHAKEx4
89 | ifneq "$(ARCH)" "ARM"
90 | SHAKEx4_OBJS := $(addprefix objs/sha3/, fips202x4.o keccak4x/KeccakP-1600-times4-SIMD256.o)
91 | SHAKEx4_HEADERS := $(addprefix src/sha3/, fips202x4.h keccak4x/KeccakP-1600-times4-SnP.h)
92 | $(SHAKEx4_OBJS): $(SHAKEx4_HEADERS)
93 | endif
94 |
95 | # KEX
96 | objs/kex/kex.o: src/kex.h
97 |
98 | RAND_OBJS := $(RAND_URANDOM_AESCTR_OBJS) $(RAND_URANDOM_CHACHA_OBJS) objs/random/rand.o
99 |
100 | KEX_OBJS := $(KEX_LWE_FRODO_OBJS) objs/kex.o
101 |
102 | lib: $(RAND_OBJS) $(KEX_OBJS) $(AES_OBJS) $(SHAKE_OBJS) $(SHAKEx4_OBJS)
103 | rm -f libfrodo.a
104 | $(AR) libfrodo.a $^
105 | $(RANLIB) libfrodo.a
106 |
107 | tests: lib src/random/test_rand.c tests/test_kex.c src/aes/test_aes.c tests/ds_benchmark.h
108 | $(CC) $(CFLAGS) $(INCLUDES) -L. src/random/test_rand.c -lfrodo $(LDFLAGS) -o test_rand
109 | $(CC) $(CFLAGS) $(INCLUDES) -L. tests/test_kex.c -lfrodo $(LDFLAGS) -o test_kex
110 | $(CC) $(CFLAGS) $(INCLUDES) -L. src/aes/test_aes.c -lfrodo $(LDFLAGS) -o test_aes
111 |
112 | docs: links
113 | doxygen
114 |
115 | check: links tests
116 | ./test_kex
117 | ./test_rand
118 | ./test_aes
119 |
120 | clean:
121 | rm -rf docs objs include
122 | rm -f test_rand test_kex test_aes libfrodo.a
123 | find . -name .DS_Store -type f -delete
124 |
125 | prettyprint:
126 | astyle --style=java --indent=tab --pad-header --pad-oper --align-pointer=name --align-reference=name --suffix=none src/*.h src/*/*.h src/*/*.c
127 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | LWE Library
2 | ===========
3 |
4 | This library implements Frodo, a lattice-based key exchange based on the Learning with Errors (LWE) problem.
5 | The library uses Frodo's "recommended parameters". See [1] for details.
6 |
7 | The library was developed by Microsoft Research for experimentation purposes.
8 |
9 | Building and Running
10 | --------------------
11 |
12 | On Windows, the library builds with Visual Studio 2015, using the solution file (frodo.sln) in the "VisualStudio" folder. It has been tested with Windows 10.
13 | On Linux, the library builds with GNU GCC or clang. It has been tested on Ubuntu 16.04 using GNU GCC version 5.4, and clang 3.8.
14 |
15 | ### Linux
16 |
17 | To build, type with the following options:
18 |
19 | $ make ARCH=[x64/x86/ARM] CC=[gcc/clang] USE_REFERENCE=[TRUE/FALSE] USE_AVX2=[TRUE/FALSE] AES_NI=[TRUE/FALSE]
20 |
21 | When simply typing:
22 |
23 | $make
24 |
25 | the library is built using ARCH=x64, CC=gcc, USE_REFERENCE=FALSE, USE_AVX2=TRUE and AES_NI=TRUE, by default.
26 |
27 | Building generates:
28 |
29 | - `libfrodo.a`: a static library based on Frodo.
30 | - `test_aes`: a test harness for AES.
31 | - `test_rand`: a test harness for the random number generator.
32 | - `test_kex`: a test harness for Frodo.
33 |
34 | To run the tests for Frodo, simply type:
35 |
36 | $ ./test_kex
37 |
38 | License
39 | -------
40 |
41 | The library is licensed under the MIT License. Part of the implementation is based on liboqs, also released under MIT.
42 | The library includes third party modules which have been released as public domain. Specifically:
43 |
44 | - `src/aes/aes.c`: public domain
45 | - `src/aes/aes_c.c`: public domain
46 | - `src/aes/aes_ni.c`: public domain
47 | - `src/sha3/fips202.c`: public domain
48 | - `src/sha3/fips202x4.c`: public domain
49 |
50 | Reference
51 | ---------
52 | [1] Joppe W. Bos, Craig Costello, Leo Ducas, Ilya Mironov, Michael Naehrig, Valeria Nikolaenko, Ananth Raghunathan, and Douglas Stebila, "Frodo: Take off the Ring! Practical, Quantum-Secure Key Exchange from LWE".
53 | ACM CCS 2016, 2016. The extended version is available at: https://eprint.iacr.org/2016/659.
54 |
55 | # Contributing
56 |
57 | This project welcomes contributions and suggestions. Most contributions require you to agree to a
58 | Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
59 | the rights to use your contribution. For details, visit https://cla.microsoft.com.
60 |
61 | When you submit a pull request, a CLA-bot will automatically determine whether you need to provide
62 | a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions
63 | provided by the bot. You will only need to do this once across all repos using our CLA.
64 |
65 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
66 | For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
67 | contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
68 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## Security
4 |
5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
6 |
7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below.
8 |
9 | ## Reporting Security Issues
10 |
11 | **Please do not report security vulnerabilities through public GitHub issues.**
12 |
13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report).
14 |
15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey).
16 |
17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc).
18 |
19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
20 |
21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
22 | * Full paths of source file(s) related to the manifestation of the issue
23 | * The location of the affected source code (tag/branch/commit or direct URL)
24 | * Any special configuration required to reproduce the issue
25 | * Step-by-step instructions to reproduce the issue
26 | * Proof-of-concept or exploit code (if possible)
27 | * Impact of the issue, including how an attacker might exploit the issue
28 |
29 | This information will help us triage your report more quickly.
30 |
31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs.
32 |
33 | ## Preferred Languages
34 |
35 | We prefer all communications to be in English.
36 |
37 | ## Policy
38 |
39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd).
40 |
41 |
42 |
--------------------------------------------------------------------------------
/VisualStudio/frodo.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.25420.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_rand", "test_rand\test_rand.vcxproj", "{6BB96591-0BCD-42E6-8863-4B9BFE75530C}"
7 | ProjectSection(ProjectDependencies) = postProject
8 | {DCFEFB81-4696-45D2-9FCA-351CCFC13C74} = {DCFEFB81-4696-45D2-9FCA-351CCFC13C74}
9 | EndProjectSection
10 | EndProject
11 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_kex", "test_kex\test_kex.vcxproj", "{820B79FE-57D7-4539-A0CA-B668A0723B9B}"
12 | ProjectSection(ProjectDependencies) = postProject
13 | {DCFEFB81-4696-45D2-9FCA-351CCFC13C74} = {DCFEFB81-4696-45D2-9FCA-351CCFC13C74}
14 | EndProjectSection
15 | EndProject
16 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Frodo", "frodo.vcxproj", "{DCFEFB81-4696-45D2-9FCA-351CCFC13C74}"
17 | EndProject
18 | Global
19 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
20 | Debug|x64 = Debug|x64
21 | Debug|x86 = Debug|x86
22 | Reference|x64 = Reference|x64
23 | Reference|x86 = Reference|x86
24 | Release|x64 = Release|x64
25 | Release|x86 = Release|x86
26 | EndGlobalSection
27 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
28 | {6BB96591-0BCD-42E6-8863-4B9BFE75530C}.Debug|x64.ActiveCfg = Debug|x64
29 | {6BB96591-0BCD-42E6-8863-4B9BFE75530C}.Debug|x64.Build.0 = Debug|x64
30 | {6BB96591-0BCD-42E6-8863-4B9BFE75530C}.Debug|x86.ActiveCfg = Debug|Win32
31 | {6BB96591-0BCD-42E6-8863-4B9BFE75530C}.Debug|x86.Build.0 = Debug|Win32
32 | {6BB96591-0BCD-42E6-8863-4B9BFE75530C}.Reference|x64.ActiveCfg = Reference|x64
33 | {6BB96591-0BCD-42E6-8863-4B9BFE75530C}.Reference|x64.Build.0 = Reference|x64
34 | {6BB96591-0BCD-42E6-8863-4B9BFE75530C}.Reference|x86.ActiveCfg = Reference|Win32
35 | {6BB96591-0BCD-42E6-8863-4B9BFE75530C}.Reference|x86.Build.0 = Reference|Win32
36 | {6BB96591-0BCD-42E6-8863-4B9BFE75530C}.Release|x64.ActiveCfg = Release|x64
37 | {6BB96591-0BCD-42E6-8863-4B9BFE75530C}.Release|x64.Build.0 = Release|x64
38 | {6BB96591-0BCD-42E6-8863-4B9BFE75530C}.Release|x86.ActiveCfg = Release|Win32
39 | {6BB96591-0BCD-42E6-8863-4B9BFE75530C}.Release|x86.Build.0 = Release|Win32
40 | {820B79FE-57D7-4539-A0CA-B668A0723B9B}.Debug|x64.ActiveCfg = Debug|x64
41 | {820B79FE-57D7-4539-A0CA-B668A0723B9B}.Debug|x64.Build.0 = Debug|x64
42 | {820B79FE-57D7-4539-A0CA-B668A0723B9B}.Debug|x86.ActiveCfg = Debug|Win32
43 | {820B79FE-57D7-4539-A0CA-B668A0723B9B}.Debug|x86.Build.0 = Debug|Win32
44 | {820B79FE-57D7-4539-A0CA-B668A0723B9B}.Reference|x64.ActiveCfg = Reference|x64
45 | {820B79FE-57D7-4539-A0CA-B668A0723B9B}.Reference|x64.Build.0 = Reference|x64
46 | {820B79FE-57D7-4539-A0CA-B668A0723B9B}.Reference|x86.ActiveCfg = Reference|Win32
47 | {820B79FE-57D7-4539-A0CA-B668A0723B9B}.Reference|x86.Build.0 = Reference|Win32
48 | {820B79FE-57D7-4539-A0CA-B668A0723B9B}.Release|x64.ActiveCfg = Release|x64
49 | {820B79FE-57D7-4539-A0CA-B668A0723B9B}.Release|x64.Build.0 = Release|x64
50 | {820B79FE-57D7-4539-A0CA-B668A0723B9B}.Release|x86.ActiveCfg = Release|Win32
51 | {820B79FE-57D7-4539-A0CA-B668A0723B9B}.Release|x86.Build.0 = Release|Win32
52 | {DCFEFB81-4696-45D2-9FCA-351CCFC13C74}.Debug|x64.ActiveCfg = Debug|x64
53 | {DCFEFB81-4696-45D2-9FCA-351CCFC13C74}.Debug|x64.Build.0 = Debug|x64
54 | {DCFEFB81-4696-45D2-9FCA-351CCFC13C74}.Debug|x86.ActiveCfg = Debug|Win32
55 | {DCFEFB81-4696-45D2-9FCA-351CCFC13C74}.Debug|x86.Build.0 = Debug|Win32
56 | {DCFEFB81-4696-45D2-9FCA-351CCFC13C74}.Reference|x64.ActiveCfg = Reference|x64
57 | {DCFEFB81-4696-45D2-9FCA-351CCFC13C74}.Reference|x64.Build.0 = Reference|x64
58 | {DCFEFB81-4696-45D2-9FCA-351CCFC13C74}.Reference|x86.ActiveCfg = Reference|Win32
59 | {DCFEFB81-4696-45D2-9FCA-351CCFC13C74}.Reference|x86.Build.0 = Reference|Win32
60 | {DCFEFB81-4696-45D2-9FCA-351CCFC13C74}.Release|x64.ActiveCfg = Release|x64
61 | {DCFEFB81-4696-45D2-9FCA-351CCFC13C74}.Release|x64.Build.0 = Release|x64
62 | {DCFEFB81-4696-45D2-9FCA-351CCFC13C74}.Release|x86.ActiveCfg = Release|Win32
63 | {DCFEFB81-4696-45D2-9FCA-351CCFC13C74}.Release|x86.Build.0 = Release|Win32
64 | EndGlobalSection
65 | GlobalSection(SolutionProperties) = preSolution
66 | HideSolutionNode = FALSE
67 | EndGlobalSection
68 | EndGlobal
69 |
--------------------------------------------------------------------------------
/VisualStudio/frodo.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Source Files\AES
6 |
7 |
8 | Source Files\AES
9 |
10 |
11 | Source Files\AES
12 |
13 |
14 | Source Files\random
15 |
16 |
17 | Source Files\random
18 |
19 |
20 | Source Files
21 |
22 |
23 | Source Files
24 |
25 |
26 | Source Files
27 |
28 |
29 | Source Files
30 |
31 |
32 | Source Files
33 |
34 |
35 | Source Files
36 |
37 |
38 | Source Files\random
39 |
40 |
41 | Source Files\sha3
42 |
43 |
44 | Source Files
45 |
46 |
47 | Source Files\sha3
48 |
49 |
50 | Source Files\sha3\fips202x4
51 |
52 |
53 |
54 |
55 | Source Files\AES
56 |
57 |
58 | Source Files\random
59 |
60 |
61 | Source Files\random
62 |
63 |
64 | Header Files
65 |
66 |
67 | Header Files
68 |
69 |
70 | Header Files
71 |
72 |
73 | Header Files
74 |
75 |
76 | Source Files\random
77 |
78 |
79 | Source Files\sha3
80 |
81 |
82 | Source Files\sha3
83 |
84 |
85 | Source Files\sha3\fips202x4
86 |
87 |
88 | Source Files\sha3\fips202x4
89 |
90 |
91 | Source Files\sha3\fips202x4
92 |
93 |
94 | Source Files\sha3\fips202x4
95 |
96 |
97 |
98 |
99 | {47469e83-ec7a-4d69-baf0-ab15e961629e}
100 |
101 |
102 | {7041c366-2ed8-4a00-8e92-4f6e2471eb9d}
103 |
104 |
105 | {71c917ec-9181-4b88-bdfc-9611ee1abe9a}
106 |
107 |
108 | {fd44eb34-2f81-411e-a55f-f279c4b101de}
109 |
110 |
111 | {656e58e0-96ef-4f93-9711-0ebe15c55da2}
112 |
113 |
114 | {a4e39759-10c0-4a8e-bbf8-6462b7fe0c2f}
115 |
116 |
117 |
118 |
119 | Source Files\sha3\fips202x4
120 |
121 |
122 |
--------------------------------------------------------------------------------
/VisualStudio/test_kex/test_kex.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Reference
10 | Win32
11 |
12 |
13 | Reference
14 | x64
15 |
16 |
17 | Release
18 | Win32
19 |
20 |
21 | Debug
22 | x64
23 |
24 |
25 | Release
26 | x64
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | {820B79FE-57D7-4539-A0CA-B668A0723B9B}
37 | Win32Proj
38 | test_kex
39 | 8.1
40 |
41 |
42 |
43 | Application
44 | true
45 | v140
46 | Unicode
47 |
48 |
49 | Application
50 | false
51 | v140
52 | true
53 | Unicode
54 |
55 |
56 | Application
57 | false
58 | v140
59 | true
60 | Unicode
61 |
62 |
63 | Application
64 | true
65 | v140
66 | Unicode
67 |
68 |
69 | Application
70 | false
71 | v140
72 | true
73 | Unicode
74 |
75 |
76 | Application
77 | false
78 | v140
79 | true
80 | Unicode
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 | true
108 | $(SolutionDir)$(Platform)\$(Configuration)\
109 | $(Platform)\$(Configuration)\
110 |
111 |
112 |
113 |
114 |
115 | true
116 |
117 |
118 |
119 |
120 |
121 | false
122 | $(SolutionDir)$(Platform)\$(Configuration)\
123 | $(Platform)\$(Configuration)\
124 |
125 |
126 |
127 |
128 |
129 | false
130 | $(SolutionDir)$(Platform)\$(Configuration)\
131 | $(Platform)\$(Configuration)\
132 |
133 |
134 |
135 |
136 |
137 | false
138 |
139 |
140 |
141 |
142 |
143 | false
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 | Level3
153 | Disabled
154 | WINDOWS;_X86_;_CRT_SECURE_NO_WARNINGS;
155 | true
156 |
157 |
158 | MultiThreadedDebug
159 |
160 |
161 | Console
162 | true
163 | $(SolutionDir)$(Platform)\$(Configuration)\;%(AdditionalLibraryDirectories)
164 | kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;frodo.lib;%(AdditionalDependencies)
165 |
166 |
167 | false
168 |
169 |
170 |
171 |
172 |
173 |
174 | Level3
175 | Disabled
176 | WINDOWS;_AMD64_;_CRT_SECURE_NO_WARNINGS;
177 | true
178 |
179 |
180 | MultiThreadedDebug
181 |
182 |
183 | Console
184 | true
185 | $(SolutionDir)$(Platform)\$(Configuration)\;%(AdditionalLibraryDirectories)
186 | kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;frodo.lib;%(AdditionalDependencies)
187 |
188 |
189 | false
190 |
191 |
192 |
193 |
194 | Level3
195 |
196 |
197 | Disabled
198 | true
199 | true
200 | WINDOWS;_X86_;_CRT_SECURE_NO_WARNINGS;
201 | true
202 |
203 |
204 | MultiThreaded
205 |
206 |
207 | Console
208 | true
209 | true
210 | true
211 | $(SolutionDir)$(Platform)\$(Configuration)\;%(AdditionalLibraryDirectories)
212 | kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;frodo.lib;%(AdditionalDependencies)
213 |
214 |
215 | false
216 |
217 |
218 |
219 |
220 | Level3
221 |
222 |
223 | Disabled
224 | true
225 | true
226 | WINDOWS;_X86_;_CRT_SECURE_NO_WARNINGS;
227 | true
228 |
229 |
230 | MultiThreaded
231 |
232 |
233 | Console
234 | true
235 | true
236 | true
237 | $(SolutionDir)$(Platform)\$(Configuration)\;%(AdditionalLibraryDirectories)
238 | kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;frodo.lib;%(AdditionalDependencies)
239 |
240 |
241 | false
242 |
243 |
244 |
245 |
246 | Level3
247 |
248 |
249 | Disabled
250 | true
251 | true
252 | WINDOWS;_AMD64_;_CRT_SECURE_NO_WARNINGS;
253 | true
254 |
255 |
256 | MultiThreaded
257 |
258 |
259 | Console
260 | true
261 | true
262 | true
263 | $(SolutionDir)$(Platform)\$(Configuration)\;%(AdditionalLibraryDirectories)
264 | kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;frodo.lib;%(AdditionalDependencies)
265 |
266 |
267 | false
268 |
269 |
270 |
271 |
272 | Level3
273 |
274 |
275 | Disabled
276 | true
277 | true
278 | WINDOWS;_AMD64_;_CRT_SECURE_NO_WARNINGS;
279 | true
280 |
281 |
282 | MultiThreaded
283 |
284 |
285 | Console
286 | true
287 | true
288 | true
289 | $(SolutionDir)$(Platform)\$(Configuration)\;%(AdditionalLibraryDirectories)
290 | kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;frodo.lib;%(AdditionalDependencies)
291 |
292 |
293 | false
294 |
295 |
296 |
297 |
298 |
299 |
--------------------------------------------------------------------------------
/VisualStudio/test_kex/test_kex.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Source Files
20 |
21 |
22 |
23 |
24 | Header Files
25 |
26 |
27 |
--------------------------------------------------------------------------------
/VisualStudio/test_rand/test_rand.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Reference
10 | Win32
11 |
12 |
13 | Reference
14 | x64
15 |
16 |
17 | Release
18 | Win32
19 |
20 |
21 | Debug
22 | x64
23 |
24 |
25 | Release
26 | x64
27 |
28 |
29 |
30 |
31 |
32 |
33 | {6BB96591-0BCD-42E6-8863-4B9BFE75530C}
34 | Win32Proj
35 | test_rand
36 | 8.1
37 |
38 |
39 |
40 | Application
41 | true
42 | v140
43 | Unicode
44 |
45 |
46 | Application
47 | false
48 | v140
49 | true
50 | Unicode
51 |
52 |
53 | Application
54 | false
55 | v140
56 | true
57 | Unicode
58 |
59 |
60 | Application
61 | true
62 | v140
63 | Unicode
64 |
65 |
66 | Application
67 | false
68 | v140
69 | true
70 | Unicode
71 |
72 |
73 | Application
74 | false
75 | v140
76 | true
77 | Unicode
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 | true
105 | $(SolutionDir)$(Platform)\$(Configuration)\
106 | $(Platform)\$(Configuration)\
107 |
108 |
109 |
110 |
111 |
112 | true
113 |
114 |
115 |
116 |
117 |
118 | false
119 | $(SolutionDir)$(Platform)\$(Configuration)\
120 | $(Platform)\$(Configuration)\
121 |
122 |
123 |
124 |
125 |
126 | false
127 | $(SolutionDir)$(Platform)\$(Configuration)\
128 | $(Platform)\$(Configuration)\
129 |
130 |
131 |
132 |
133 |
134 | false
135 |
136 |
137 |
138 |
139 |
140 | false
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 | Level3
150 | Disabled
151 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
152 | true
153 |
154 |
155 | MultiThreadedDebug
156 |
157 |
158 | Console
159 | true
160 | kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;frodo.lib;%(AdditionalDependencies)
161 | $(SolutionDir)$(Platform)\$(Configuration)\;%(AdditionalLibraryDirectories)
162 |
163 |
164 |
165 |
166 |
167 |
168 | Level3
169 | Disabled
170 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
171 | true
172 |
173 |
174 | MultiThreadedDebug
175 |
176 |
177 | Console
178 | true
179 | kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;frodo.lib;%(AdditionalDependencies)
180 | $(SolutionDir)$(Platform)\$(Configuration)\;%(AdditionalLibraryDirectories)
181 |
182 |
183 |
184 |
185 | Level3
186 |
187 |
188 | Disabled
189 | true
190 | true
191 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
192 | true
193 |
194 |
195 | MultiThreaded
196 |
197 |
198 | Console
199 | true
200 | true
201 | true
202 | kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;frodo.lib;%(AdditionalDependencies)
203 | $(SolutionDir)$(Platform)\$(Configuration)\;%(AdditionalLibraryDirectories)
204 |
205 |
206 |
207 |
208 | Level3
209 |
210 |
211 | Disabled
212 | true
213 | true
214 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
215 | true
216 |
217 |
218 | MultiThreaded
219 |
220 |
221 | Console
222 | true
223 | true
224 | true
225 | kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;frodo.lib;%(AdditionalDependencies)
226 | $(SolutionDir)$(Platform)\$(Configuration)\;%(AdditionalLibraryDirectories)
227 |
228 |
229 |
230 |
231 | Level3
232 |
233 |
234 | Disabled
235 | true
236 | true
237 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
238 | true
239 |
240 |
241 | MultiThreaded
242 |
243 |
244 | Console
245 | true
246 | true
247 | true
248 | kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;frodo.lib;%(AdditionalDependencies)
249 | $(SolutionDir)$(Platform)\$(Configuration)\;%(AdditionalLibraryDirectories)
250 |
251 |
252 |
253 |
254 | Level3
255 |
256 |
257 | Disabled
258 | true
259 | true
260 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
261 | true
262 |
263 |
264 | MultiThreaded
265 |
266 |
267 | Console
268 | true
269 | true
270 | true
271 | kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;frodo.lib;%(AdditionalDependencies)
272 | $(SolutionDir)$(Platform)\$(Configuration)\;%(AdditionalLibraryDirectories)
273 |
274 |
275 |
276 |
277 |
278 |
--------------------------------------------------------------------------------
/VisualStudio/test_rand/test_rand.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Source Files
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/aes/aes.c:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include "aes.h"
4 | #include "aes_local.h"
5 |
6 | void OQS_AES128_load_schedule(const uint8_t *key, void **schedule, int for_encryption) {
7 | #ifdef USE_OPENSSL
8 | oqs_aes128_load_schedule_ossl(key, schedule, for_encryption);
9 | #else
10 | for_encryption++; // need some dummy operation to avoid unused parameter warning
11 | #ifdef AES_ENABLE_NI
12 | oqs_aes128_load_schedule_ni(key, schedule);
13 | #else
14 | oqs_aes128_load_schedule_c(key, schedule);
15 | #endif
16 | #endif
17 | }
18 |
19 | void OQS_AES128_free_schedule(void *schedule) {
20 | #ifdef USE_OPENSSL
21 | oqs_aes128_free_schedule_ossl(schedule);
22 | #else
23 | #ifdef AES_ENABLE_NI
24 | oqs_aes128_free_schedule_ni(schedule);
25 | #else
26 | oqs_aes128_free_schedule_c(schedule);
27 | #endif
28 | #endif
29 | }
30 |
31 | void OQS_AES128_ECB_enc(const uint8_t *plaintext, const size_t plaintext_len, const uint8_t *key, uint8_t *ciphertext) {
32 | #ifdef USE_OPENSSL
33 | oqs_aes128_ecb_enc_ossl(plaintext, plaintext_len, key, ciphertext);
34 | #else
35 | #ifdef AES_ENABLE_NI
36 | oqs_aes128_ecb_enc_ni(plaintext, plaintext_len, key, ciphertext);
37 | #else
38 | oqs_aes128_ecb_enc_c(plaintext, plaintext_len, key, ciphertext);
39 | #endif
40 | #endif
41 | }
42 |
43 | void OQS_AES128_ECB_dec(const uint8_t *ciphertext, const size_t ciphertext_len, const uint8_t *key, uint8_t *plaintext) {
44 | #ifdef USE_OPENSSL
45 | oqs_aes128_ecb_dec_ossl(ciphertext, ciphertext_len, key, plaintext);
46 | #else
47 | #ifdef AES_ENABLE_NI
48 | oqs_aes128_ecb_dec_ni(ciphertext, ciphertext_len, key, plaintext);
49 | #else
50 | oqs_aes128_ecb_dec_c(ciphertext, ciphertext_len, key, plaintext);
51 | #endif
52 | #endif
53 | }
54 |
55 | void OQS_AES128_ECB_enc_sch(const uint8_t *plaintext, const size_t plaintext_len, const void *schedule, uint8_t *ciphertext) {
56 | #ifdef USE_OPENSSL
57 | oqs_aes128_ecb_enc_sch_ossl(plaintext, plaintext_len, schedule, ciphertext);
58 | #else
59 | #ifdef AES_ENABLE_NI
60 | oqs_aes128_ecb_enc_sch_ni(plaintext, plaintext_len, schedule, ciphertext);
61 | #else
62 | oqs_aes128_ecb_enc_sch_c(plaintext, plaintext_len, schedule, ciphertext);
63 | #endif
64 | #endif
65 | }
66 |
67 | void OQS_AES128_ECB_dec_sch(const uint8_t *ciphertext, const size_t ciphertext_len, const void *schedule, uint8_t *plaintext) {
68 | #ifdef USE_OPENSSL
69 | oqs_aes128_ecb_dec_sch_ossl(ciphertext, ciphertext_len, schedule, plaintext);
70 | #else
71 | #ifdef AES_ENABLE_NI
72 | oqs_aes128_ecb_dec_sch_ni(ciphertext, ciphertext_len, schedule, plaintext);
73 | #else
74 | oqs_aes128_ecb_dec_sch_c(ciphertext, ciphertext_len, schedule, plaintext);
75 | #endif
76 | #endif
77 | }
78 |
79 | #ifdef AES_ENABLE_NI
80 | inline void oqs_aes128_ecb_enc_ni(const uint8_t *plaintext, const size_t plaintext_len, const uint8_t *key, uint8_t *ciphertext) {
81 | void *schedule = NULL;
82 | oqs_aes128_load_schedule_ni(key, &schedule);
83 | oqs_aes128_ecb_enc_sch_ni(plaintext, plaintext_len, schedule, ciphertext);
84 | oqs_aes128_free_schedule_ni(schedule);
85 | }
86 | #endif
87 |
88 | inline void oqs_aes128_ecb_enc_c(const uint8_t *plaintext, const size_t plaintext_len, const uint8_t *key, uint8_t *ciphertext) {
89 | void *schedule = NULL;
90 | oqs_aes128_load_schedule_c(key, &schedule);
91 | oqs_aes128_ecb_enc_sch_c(plaintext, plaintext_len, schedule, ciphertext);
92 | oqs_aes128_free_schedule_c(schedule);
93 | }
94 |
95 | #ifdef AES_ENABLE_NI
96 | inline void oqs_aes128_ecb_enc_sch_ni(const uint8_t *plaintext, const size_t plaintext_len, const void *schedule, uint8_t *ciphertext) {
97 | assert(plaintext_len % 16 == 0);
98 | for (size_t block = 0; block < plaintext_len / 16; block++) {
99 | oqs_aes128_enc_ni(plaintext + (16 * block), schedule, ciphertext + (16 * block));
100 | }
101 | }
102 | #endif
103 |
104 | inline void oqs_aes128_ecb_enc_sch_c(const uint8_t *plaintext, const size_t plaintext_len, const void *schedule, uint8_t *ciphertext) {
105 | assert(plaintext_len % 16 == 0);
106 | for (size_t block = 0; block < plaintext_len / 16; block++) {
107 | oqs_aes128_enc_c(plaintext + (16 * block), schedule, ciphertext + (16 * block));
108 | }
109 | }
110 |
111 | #ifdef AES_ENABLE_NI
112 | inline void oqs_aes128_ecb_dec_ni(const uint8_t *ciphertext, const size_t ciphertext_len, const uint8_t *key, uint8_t *plaintext) {
113 | void *schedule = NULL;
114 | oqs_aes128_load_schedule_ni(key, &schedule);
115 | oqs_aes128_ecb_dec_sch_ni(ciphertext, ciphertext_len, schedule, plaintext);
116 | oqs_aes128_free_schedule_ni(schedule);
117 | }
118 | #endif
119 |
120 | inline void oqs_aes128_ecb_dec_c(const uint8_t *ciphertext, const size_t ciphertext_len, const uint8_t *key, uint8_t *plaintext) {
121 | void *schedule = NULL;
122 | oqs_aes128_load_schedule_c(key, &schedule);
123 | oqs_aes128_ecb_dec_sch_c(ciphertext, ciphertext_len, schedule, plaintext);
124 | oqs_aes128_free_schedule_c(schedule);
125 | }
126 |
127 | #ifdef AES_ENABLE_NI
128 | inline void oqs_aes128_ecb_dec_sch_ni(const uint8_t *ciphertext, const size_t ciphertext_len, const void *schedule, uint8_t *plaintext) {
129 | assert(ciphertext_len % 16 == 0);
130 | for (size_t block = 0; block < ciphertext_len / 16; block++) {
131 | oqs_aes128_dec_ni(ciphertext + (16 * block), schedule, plaintext + (16 * block));
132 | }
133 | }
134 | #endif
135 |
136 | inline void oqs_aes128_ecb_dec_sch_c(const uint8_t *ciphertext, const size_t ciphertext_len, const void *schedule, uint8_t *plaintext) {
137 | assert(ciphertext_len % 16 == 0);
138 | for (size_t block = 0; block < ciphertext_len / 16; block++) {
139 | oqs_aes128_dec_c(ciphertext + (16 * block), schedule, plaintext + (16 * block));
140 | }
141 | }
142 |
143 | #ifdef USE_OPENSSL
144 | #include
145 |
146 | inline void oqs_aes128_load_schedule_ossl(const uint8_t *key, void **schedule, int for_encryption) {
147 | EVP_CIPHER_CTX *aes_ctx = EVP_CIPHER_CTX_new();
148 | assert(aes_ctx != NULL);
149 | if (for_encryption) {
150 | assert(1 == EVP_EncryptInit_ex(aes_ctx, EVP_aes_128_ecb(), NULL, key, NULL));
151 | } else {
152 | assert(1 == EVP_DecryptInit_ex(aes_ctx, EVP_aes_128_ecb(), NULL, key, NULL));
153 | }
154 | EVP_CIPHER_CTX_set_padding(aes_ctx, 0);
155 | *schedule = aes_ctx;
156 | }
157 |
158 | inline void oqs_aes128_free_schedule_ossl(void *schedule) {
159 | if (schedule != NULL) {
160 | EVP_CIPHER_CTX_free((EVP_CIPHER_CTX *) schedule);
161 | }
162 | }
163 |
164 | inline void oqs_aes128_ecb_enc_ossl(const uint8_t *plaintext, const size_t plaintext_len, const uint8_t *key, uint8_t *ciphertext) {
165 | void *schedule = NULL;
166 | oqs_aes128_load_schedule_ossl(key, &schedule, 1);
167 | oqs_aes128_ecb_enc_sch_ossl(plaintext, plaintext_len, schedule, ciphertext);
168 | oqs_aes128_free_schedule_ossl(schedule);
169 | }
170 |
171 | inline void oqs_aes128_ecb_dec_ossl(const uint8_t *ciphertext, const size_t ciphertext_len, const uint8_t *key, uint8_t *plaintext) {
172 | void *schedule = NULL;
173 | oqs_aes128_load_schedule_ossl(key, &schedule, 0);
174 | oqs_aes128_ecb_dec_sch_ossl(ciphertext, ciphertext_len, schedule, plaintext);
175 | oqs_aes128_free_schedule_ossl(schedule);
176 | }
177 |
178 | inline void oqs_aes128_ecb_enc_sch_ossl(const uint8_t *plaintext, const size_t plaintext_len, const void *schedule, uint8_t *ciphertext) {
179 | assert(plaintext_len % 16 == 0);
180 | int outlen;
181 | assert(1 == EVP_EncryptUpdate((EVP_CIPHER_CTX *) schedule, ciphertext, &outlen, plaintext, plaintext_len));
182 | assert((size_t) outlen == plaintext_len);
183 | assert(1 == EVP_EncryptFinal_ex((EVP_CIPHER_CTX *) schedule, ciphertext, &outlen));
184 | }
185 |
186 | inline void oqs_aes128_ecb_dec_sch_ossl(const uint8_t *ciphertext, const size_t ciphertext_len, const void *schedule, uint8_t *plaintext) {
187 | assert(ciphertext_len % 16 == 0);
188 | int outlen;
189 | assert(1 == EVP_DecryptUpdate((EVP_CIPHER_CTX *) schedule, plaintext, &outlen, ciphertext, ciphertext_len));
190 | assert((size_t) outlen == ciphertext_len);
191 | assert(1 == EVP_DecryptFinal_ex((EVP_CIPHER_CTX *) schedule, plaintext, &outlen));
192 | }
193 |
194 | #endif
195 |
--------------------------------------------------------------------------------
/src/aes/aes.h:
--------------------------------------------------------------------------------
1 | /**
2 | * \file aes.h
3 | * \brief Header defining the API for OQS AES
4 | */
5 |
6 | #ifndef __OQS_AES_H
7 | #define __OQS_AES_H
8 |
9 | #include
10 | #include
11 |
12 | /**
13 | * Function to fill a key schedule given an initial key.
14 | *
15 | * @param key Initial Key.
16 | * @param schedule Abstract data structure for a key schedule.
17 | * @param forEncryption 1 if key schedule is for encryption, 0 if for decryption.
18 | */
19 | void OQS_AES128_load_schedule(const uint8_t *key, void **schedule, int for_encryption);
20 |
21 | /**
22 | * Function to free a key schedule.
23 | *
24 | * @param schedule Schedule generated with OQS_AES128_load_schedule().
25 | */
26 | void OQS_AES128_free_schedule(void *schedule);
27 |
28 | /**
29 | * Function to encrypt blocks of plaintext using ECB mode.
30 | * A schedule based on the key is generated and used internally.
31 | *
32 | * @param plaintext Plaintext to be encrypted.
33 | * @param plaintext_len Length on the plaintext in bytes. Must be a multiple of 16.
34 | * @param key Key to be used for encryption.
35 | * @param ciphertext Pointer to a block of memory which >= in size to the plaintext block. The result will be written here.
36 | */
37 | void OQS_AES128_ECB_enc(const uint8_t *plaintext, const size_t plaintext_len, const uint8_t *key, uint8_t *ciphertext);
38 |
39 | /**
40 | * Function to decrypt blocks of plaintext using ECB mode.
41 | * A schedule based on the key is generated and used internally.
42 | *
43 | * @param ciphertext Ciphertext to be decrypted.
44 | * @param ciphertext_len Length on the ciphertext in bytes. Must be a multiple of 16.
45 | * @param key Key to be used for encryption.
46 | * @param ciphertext Pointer to a block of memory which >= in size to the ciphertext block. The result will be written here.
47 | */
48 | void OQS_AES128_ECB_dec(const uint8_t *ciphertext, const size_t ciphertext_len, const uint8_t *key, uint8_t *plaintext);
49 |
50 | /**
51 | * Same as OQS_AES128_ECB_enc() except a schedule generated by
52 | * OQS_AES128_load_schedule() is passed rather then a key. This is faster
53 | * if the same schedule is used for multiple encryptions since it does
54 | * not have to be regenerated from the key.
55 | */
56 | void OQS_AES128_ECB_enc_sch(const uint8_t *plaintext, const size_t plaintext_len, const void *schedule, uint8_t *ciphertext);
57 |
58 | /**
59 | * Same as OQS_AES128_ECB_dec() except a schedule generated by
60 | * OQS_AES128_load_schedule() is passed rather then a key. This is faster
61 | * if the same schedule is used for multiple encryptions since it does
62 | * not have to be regenerated from the key.
63 | */
64 | void OQS_AES128_ECB_dec_sch(const uint8_t *ciphertext, const size_t ciphertext_len, const void *schedule, uint8_t *plaintext);
65 |
66 | #endif
67 |
--------------------------------------------------------------------------------
/src/aes/aes_local.h:
--------------------------------------------------------------------------------
1 | /**
2 | * \file aes_local.h
3 | * \brief Header defining additional internal functions for OQS AES
4 | */
5 |
6 | #ifndef __OQS_AES_LOCAL_H
7 | #define __OQS_AES_LOCAL_H
8 |
9 | #include
10 | #include
11 |
12 | void oqs_aes128_load_schedule_ni(const uint8_t *key, void **schedule);
13 | void oqs_aes128_free_schedule_ni(void *schedule);
14 | void oqs_aes128_enc_ni(const uint8_t *plaintext, const void *schedule, uint8_t *ciphertext);
15 | void oqs_aes128_dec_ni(const uint8_t *ciphertext, const void *schedule, uint8_t *plaintext);
16 | void oqs_aes128_ecb_enc_ni(const uint8_t *plaintext, const size_t plaintext_len, const uint8_t *key, uint8_t *ciphertext);
17 | void oqs_aes128_ecb_dec_ni(const uint8_t *ciphertext, const size_t ciphertext_len, const uint8_t *key, uint8_t *plaintext);
18 | void oqs_aes128_ecb_enc_sch_ni(const uint8_t *plaintext, const size_t plaintext_len, const void *schedule, uint8_t *ciphertext);
19 | void oqs_aes128_ecb_dec_sch_ni(const uint8_t *ciphertext, const size_t ciphertext_len, const void *schedule, uint8_t *plaintext);
20 |
21 | void oqs_aes128_load_schedule_c(const uint8_t *key, void **schedule);
22 | void oqs_aes128_free_schedule_c(void *schedule);
23 | void oqs_aes128_enc_c(const uint8_t *plaintext, const void *schedule, uint8_t *ciphertext);
24 | void oqs_aes128_dec_c(const uint8_t *ciphertext, const void *schedule, uint8_t *plaintext);
25 | void oqs_aes128_ecb_enc_c(const uint8_t *plaintext, const size_t plaintext_len, const uint8_t *key, uint8_t *ciphertext);
26 | void oqs_aes128_ecb_dec_c(const uint8_t *ciphertext, const size_t ciphertext_len, const uint8_t *key, uint8_t *plaintext);
27 | void oqs_aes128_ecb_enc_sch_c(const uint8_t *plaintext, const size_t plaintext_len, const void *schedule, uint8_t *ciphertext);
28 | void oqs_aes128_ecb_dec_sch_c(const uint8_t *ciphertext, const size_t ciphertext_len, const void *schedule, uint8_t *plaintext);
29 |
30 | #ifdef USE_OPENSSL
31 | void oqs_aes128_load_schedule_ossl(const uint8_t *key, void **schedule, int for_encryption);
32 | void oqs_aes128_free_schedule_ossl(void *schedule);
33 | void oqs_aes128_ecb_enc_ossl(const uint8_t *plaintext, const size_t plaintext_len, const uint8_t *key, uint8_t *ciphertext);
34 | void oqs_aes128_ecb_dec_ossl(const uint8_t *ciphertext, const size_t ciphertext_len, const uint8_t *key, uint8_t *plaintext);
35 | void oqs_aes128_ecb_enc_sch_ossl(const uint8_t *plaintext, const size_t plaintext_len, const void *schedule, uint8_t *ciphertext);
36 | void oqs_aes128_ecb_dec_sch_ossl(const uint8_t *ciphertext, const size_t ciphertext_len, const void *schedule, uint8_t *plaintext);
37 | #endif
38 |
39 | #endif
40 |
--------------------------------------------------------------------------------
/src/aes/aes_ni.c:
--------------------------------------------------------------------------------
1 | #if defined(WINDOWS)
2 | #define UNUSED
3 | // __attribute__ not supported in VS, is there something else I should define?
4 | #else
5 | #define UNUSED __attribute__((unused))
6 | #endif
7 |
8 | #include
9 | #include
10 | #include
11 |
12 | #ifndef AES_ENABLE_NI
13 | #include
14 | void oqs_aes128_load_schedule_ni(UNUSED const uint8_t *key, UNUSED void **_schedule) {
15 | assert(0);
16 | }
17 | void oqs_aes128_free_schedule_ni(UNUSED void *_schedule) {
18 | assert(0);
19 | }
20 | void oqs_aes128_enc_ni(UNUSED const uint8_t *plaintext, UNUSED const void *_schedule, UNUSED uint8_t *ciphertext) {
21 | assert(0);
22 | }
23 | void oqs_aes128_dec_ni(UNUSED const uint8_t *ciphertext, UNUSED const void *_schedule, UNUSED uint8_t *plaintext) {
24 | assert(0);
25 | }
26 | #else
27 |
28 | #include
29 |
30 | static __m128i key_expand(__m128i key, __m128i keygened) {
31 | key = _mm_xor_si128(key, _mm_slli_si128(key, 4));
32 | key = _mm_xor_si128(key, _mm_slli_si128(key, 4));
33 | key = _mm_xor_si128(key, _mm_slli_si128(key, 4));
34 | // The last 4 bytes from aeskeygenassist store the values we want so
35 | // and they need to be xored all four sets of bytes in the result so
36 | keygened = _mm_shuffle_epi32(keygened, _MM_SHUFFLE(3, 3, 3, 3));
37 | return _mm_xor_si128(key, keygened);
38 | }
39 |
40 | //This is needed since the rcon argument to _mm_aeskeygenassist_si128
41 | //must be a compile time constaint
42 |
43 | #define key_exp(k, rcon) key_expand(k, _mm_aeskeygenassist_si128(k, rcon))
44 |
45 | void oqs_aes128_load_schedule_ni(const uint8_t *key, void **_schedule) {
46 | *_schedule = malloc(20 * 16);
47 | assert(*_schedule != NULL);
48 | __m128i *schedule = (__m128i *) *_schedule;
49 | schedule[0] = _mm_loadu_si128((const __m128i *) key);
50 | schedule[1] = key_exp(schedule[0], 0x01);
51 | schedule[2] = key_exp(schedule[1], 0x02);
52 | schedule[3] = key_exp(schedule[2], 0x04);
53 | schedule[4] = key_exp(schedule[3], 0x08);
54 | schedule[5] = key_exp(schedule[4], 0x10);
55 | schedule[6] = key_exp(schedule[5], 0x20);
56 | schedule[7] = key_exp(schedule[6], 0x40);
57 | schedule[8] = key_exp(schedule[7], 0x80);
58 | schedule[9] = key_exp(schedule[8], 0x1b);
59 | schedule[10] = key_exp(schedule[9], 0x36);
60 | // generate decryption keys in reverse order.
61 | // schedule[10] is shared by last encryption and first decryption rounds
62 | // schedule[0] is shared by first encryption round and last decryption round
63 | for (size_t i = 0; i < 9; i++) {
64 | schedule[11 + i] = _mm_aesimc_si128(schedule[9 - i]);
65 | }
66 | }
67 |
68 | void oqs_aes128_free_schedule_ni(void *schedule) {
69 | if (schedule != NULL) {
70 | free(schedule);
71 | }
72 | }
73 |
74 | void oqs_aes128_enc_ni(const uint8_t *plaintext, const void *_schedule, uint8_t *ciphertext) {
75 | __m128i *schedule = (__m128i *) _schedule;
76 | __m128i m = _mm_loadu_si128((__m128i *) plaintext);
77 |
78 | m = _mm_xor_si128(m, schedule[0]);
79 | for (size_t i = 1; i < 10; i++) {
80 | m = _mm_aesenc_si128(m, schedule[i]);
81 | }
82 | m = _mm_aesenclast_si128(m, schedule[10]);
83 |
84 | _mm_storeu_si128((__m128i *) ciphertext, m);
85 | }
86 |
87 | void oqs_aes128_dec_ni(const uint8_t *ciphertext, const void *_schedule, uint8_t *plaintext) {
88 | __m128i *schedule = (__m128i *) _schedule;
89 | __m128i m = _mm_loadu_si128((__m128i *) ciphertext);
90 |
91 | m = _mm_xor_si128(m, schedule[10]);
92 | for (size_t i = 1; i < 10; i++) {
93 | m = _mm_aesdec_si128(m, schedule[10 + i]);
94 | }
95 | m = _mm_aesdeclast_si128(m, schedule[0]);
96 |
97 | _mm_storeu_si128((__m128i *) plaintext, m);
98 | }
99 |
100 | #endif
101 |
--------------------------------------------------------------------------------
/src/aes/test_aes.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | #include "../random/rand.h"
7 | #include "../../tests/ds_benchmark.h"
8 | #include "aes.h"
9 | #include "aes_local.h"
10 |
11 | #define BENCH_DURATION 1
12 |
13 | #define TEST_ITERATIONS 100
14 |
15 | #define TEST_REPEATEDLY(x) \
16 | for (int i = 0; i < TEST_ITERATIONS; i++) { \
17 | int ok = (x); \
18 | if (ok != EXIT_SUCCESS) { \
19 | fprintf(stderr, "Failure in %s (iteration %d)\n", #x, i); \
20 | return EXIT_FAILURE; \
21 | } \
22 | }
23 |
24 | static void print_bytes(uint8_t *bytes, size_t num_bytes) {
25 | for (size_t i = 0; i < num_bytes; i++) {
26 | printf("%02x", (unsigned) bytes[i]);
27 | }
28 | }
29 |
30 | static int test_aes128_correctness_c(OQS_RAND *rand) {
31 | uint8_t key[16], plaintext[16], ciphertext[16], decrypted[16];
32 | void *schedule = NULL;
33 | OQS_RAND_n(rand, key, 16);
34 | OQS_RAND_n(rand, plaintext, 16);
35 | oqs_aes128_load_schedule_c(key, &schedule);
36 | oqs_aes128_enc_c(plaintext, schedule, ciphertext);
37 | oqs_aes128_dec_c(ciphertext, schedule, decrypted);
38 | oqs_aes128_free_schedule_c(schedule);
39 | if (memcmp(plaintext, decrypted, 16) == 0) {
40 | return EXIT_SUCCESS;
41 | } else {
42 | print_bytes(plaintext, 16);
43 | printf("\n");
44 | print_bytes(decrypted, 16);
45 | printf("\n");
46 | return EXIT_FAILURE;
47 | }
48 | }
49 |
50 | #ifdef AES_ENABLE_NI
51 | static int test_aes128_correctness_ni(OQS_RAND *rand) {
52 | uint8_t key[16], plaintext[16], ciphertext[16], decrypted[16];
53 | void *schedule = NULL;
54 | OQS_RAND_n(rand, key, 16);
55 | OQS_RAND_n(rand, plaintext, 16);
56 | oqs_aes128_load_schedule_ni(key, &schedule);
57 | oqs_aes128_enc_ni(plaintext, schedule, ciphertext);
58 | oqs_aes128_dec_ni(ciphertext, schedule, decrypted);
59 | oqs_aes128_free_schedule_ni(schedule);
60 | if (memcmp(plaintext, decrypted, 16) == 0) {
61 | return EXIT_SUCCESS;
62 | } else {
63 | print_bytes(plaintext, 16);
64 | printf("\n");
65 | print_bytes(decrypted, 16);
66 | printf("\n");
67 | return EXIT_FAILURE;
68 | }
69 | }
70 |
71 | static int test_aes128_c_equals_ni(OQS_RAND *rand) {
72 | uint8_t key[16], plaintext[16], ciphertext_c[16], ciphertext_ni[16];
73 | void *schedule_c = NULL, *schedule_ni = NULL;
74 | OQS_RAND_n(rand, key, 16);
75 | OQS_RAND_n(rand, plaintext, 16);
76 | oqs_aes128_load_schedule_c(key, &schedule_c);
77 | oqs_aes128_load_schedule_ni(key, &schedule_ni);
78 | oqs_aes128_enc_c(plaintext, schedule_c, ciphertext_c);
79 | oqs_aes128_enc_ni(plaintext, schedule_ni, ciphertext_ni);
80 | oqs_aes128_free_schedule_c(schedule_c);
81 | oqs_aes128_free_schedule_ni(schedule_ni);
82 | if (memcmp(ciphertext_c, ciphertext_ni, 16) == 0) {
83 | return EXIT_SUCCESS;
84 | } else {
85 | print_bytes(ciphertext_c, 16);
86 | printf("\n");
87 | print_bytes(ciphertext_ni, 16);
88 | printf("\n");
89 | return EXIT_FAILURE;
90 | }
91 | }
92 |
93 | static int test_aes128_ecb_correctness_ni(OQS_RAND *rand) {
94 | uint8_t key[16], plaintext[320], ciphertext[320], decrypted[320];
95 | void *schedule = NULL;
96 | OQS_RAND_n(rand, key, 16);
97 | OQS_RAND_n(rand, plaintext, 320);
98 | oqs_aes128_load_schedule_ni(key, &schedule);
99 | oqs_aes128_ecb_enc_ni(plaintext, 320, schedule, ciphertext);
100 | oqs_aes128_ecb_dec_ni(ciphertext, 320, schedule, decrypted);
101 | oqs_aes128_free_schedule_ni(schedule);
102 | if (memcmp(plaintext, decrypted, 320) == 0) {
103 | return EXIT_SUCCESS;
104 | } else {
105 | print_bytes(plaintext, 320);
106 | printf("\n");
107 | print_bytes(decrypted, 320);
108 | printf("\n");
109 | return EXIT_FAILURE;
110 | }
111 | }
112 | #endif
113 |
114 | static int test_aes128_ecb_correctness_c(OQS_RAND *rand) {
115 | uint8_t key[16], plaintext[320], ciphertext[320], decrypted[320];
116 | void *schedule = NULL;
117 | OQS_RAND_n(rand, key, 16);
118 | OQS_RAND_n(rand, plaintext, 320);
119 | oqs_aes128_load_schedule_c(key, &schedule);
120 | oqs_aes128_ecb_enc_c(plaintext, 320, schedule, ciphertext);
121 | oqs_aes128_ecb_dec_c(ciphertext, 320, schedule, decrypted);
122 | oqs_aes128_free_schedule_c(schedule);
123 | if (memcmp(plaintext, decrypted, 320) == 0) {
124 | return EXIT_SUCCESS;
125 | } else {
126 | print_bytes(plaintext, 320);
127 | printf("\n");
128 | print_bytes(decrypted, 320);
129 | printf("\n");
130 | return EXIT_FAILURE;
131 | }
132 | }
133 |
134 | #ifdef USE_OPENSSL
135 | static int test_aes128_ecb_correctness_ossl(OQS_RAND *rand) {
136 | uint8_t key[16], plaintext[320], ciphertext[320], decrypted[320];
137 | void *schedule = NULL;
138 | OQS_RAND_n(rand, key, 16);
139 | OQS_RAND_n(rand, plaintext, 320);
140 | oqs_aes128_load_schedule_ossl(key, &schedule, 1);
141 | oqs_aes128_ecb_enc_ossl(plaintext, 320, schedule, ciphertext);
142 | oqs_aes128_free_schedule_ossl(schedule);
143 | oqs_aes128_load_schedule_ossl(key, &schedule, 0);
144 | oqs_aes128_ecb_dec_ossl(ciphertext, 320, schedule, decrypted);
145 | oqs_aes128_free_schedule_ossl(schedule);
146 | if (memcmp(plaintext, decrypted, 320) == 0) {
147 | return EXIT_SUCCESS;
148 | } else {
149 | print_bytes(plaintext, 320);
150 | printf("\n");
151 | print_bytes(decrypted, 320);
152 | printf("\n");
153 | return EXIT_FAILURE;
154 | }
155 | }
156 | #endif
157 |
158 | static void speed_aes128_c(OQS_RAND *rand) {
159 | uint8_t key[16], plaintext[320], ciphertext[320], decrypted[320];
160 | void *schedule = NULL;
161 | OQS_RAND_n(rand, key, 16);
162 | OQS_RAND_n(rand, plaintext, 320);
163 | TIME_OPERATION_SECONDS({ oqs_aes128_load_schedule_c(key, &schedule); oqs_aes128_free_schedule_c(schedule); }, "oqs_aes128_load_schedule_c", BENCH_DURATION);
164 |
165 | oqs_aes128_load_schedule_c(key, &schedule);
166 | TIME_OPERATION_SECONDS(oqs_aes128_enc_c(plaintext, schedule, ciphertext), "oqs_aes128_enc_c", BENCH_DURATION);
167 | TIME_OPERATION_SECONDS(oqs_aes128_dec_c(ciphertext, schedule, decrypted), "oqs_aes128_dec_c", BENCH_DURATION);
168 | TIME_OPERATION_SECONDS(oqs_aes128_ecb_enc_c(plaintext, 320, key, ciphertext), "oqs_aes128_ecb_enc_c", BENCH_DURATION);
169 | TIME_OPERATION_SECONDS(oqs_aes128_ecb_dec_c(ciphertext, 320, key, decrypted), "oqs_aes128_ecb_dec_c", BENCH_DURATION);
170 | TIME_OPERATION_SECONDS(oqs_aes128_ecb_enc_sch_c(plaintext, 320, schedule, ciphertext), "oqs_aes128_ecb_enc_sch_c", BENCH_DURATION);
171 | TIME_OPERATION_SECONDS(oqs_aes128_ecb_dec_sch_c(ciphertext, 320, schedule, decrypted), "oqs_aes128_ecb_dec_sch_c", BENCH_DURATION);
172 | oqs_aes128_free_schedule_c(schedule);
173 | }
174 |
175 | #ifdef AES_ENABLE_NI
176 |
177 | static void speed_aes128_ni(OQS_RAND *rand) {
178 | uint8_t key[16], plaintext[320], ciphertext[320], decrypted[320];
179 | void *schedule = NULL;
180 | OQS_RAND_n(rand, key, 16);
181 | OQS_RAND_n(rand, plaintext, 320);
182 | TIME_OPERATION_SECONDS({ oqs_aes128_load_schedule_ni(key, &schedule); oqs_aes128_free_schedule_ni(schedule); }, "oqs_aes128_load_schedule_ni", BENCH_DURATION);
183 |
184 | oqs_aes128_load_schedule_ni(key, &schedule);
185 | TIME_OPERATION_SECONDS(oqs_aes128_enc_ni(plaintext, schedule, ciphertext), "oqs_aes128_enc_ni", BENCH_DURATION);
186 | TIME_OPERATION_SECONDS(oqs_aes128_dec_ni(ciphertext, schedule, decrypted), "oqs_aes128_dec_ni", BENCH_DURATION);
187 | TIME_OPERATION_SECONDS(oqs_aes128_ecb_enc_ni(plaintext, 320, key, ciphertext), "oqs_aes128_ecb_enc_ni", BENCH_DURATION);
188 | TIME_OPERATION_SECONDS(oqs_aes128_ecb_dec_ni(ciphertext, 320, key, decrypted), "oqs_aes128_ecb_dec_ni", BENCH_DURATION);
189 | TIME_OPERATION_SECONDS(oqs_aes128_ecb_enc_sch_ni(plaintext, 320, schedule, ciphertext), "oqs_aes128_ecb_enc_sch_ni", BENCH_DURATION);
190 | TIME_OPERATION_SECONDS(oqs_aes128_ecb_dec_sch_ni(ciphertext, 320, schedule, decrypted), "oqs_aes128_ecb_dec_sch_ni", BENCH_DURATION);
191 | oqs_aes128_free_schedule_ni(schedule);
192 | }
193 | #endif
194 |
195 | #ifdef USE_OPENSSL
196 | static void speed_aes128_ossl(OQS_RAND *rand) {
197 | uint8_t key[16], plaintext[320], ciphertext[320];
198 | void *schedule = NULL;
199 | OQS_RAND_n(rand, key, 16);
200 | OQS_RAND_n(rand, plaintext, 320);
201 | TIME_OPERATION_SECONDS(oqs_aes128_load_schedule_ossl(key, &schedule, 1), "oqs_aes128_load_schedule_ossl 1", BENCH_DURATION);
202 | TIME_OPERATION_SECONDS(oqs_aes128_load_schedule_ossl(key, &schedule, 0), "oqs_aes128_load_schedule_ossl 0", BENCH_DURATION);
203 | TIME_OPERATION_SECONDS(oqs_aes128_ecb_enc_ossl(plaintext, 320, key, ciphertext), "oqs_aes128_ecb_enc_ossl", BENCH_DURATION);
204 | TIME_OPERATION_SECONDS(oqs_aes128_ecb_dec_ossl(ciphertext, 320, key, plaintext), "oqs_aes128_ecb_dec_ossl", BENCH_DURATION);
205 | oqs_aes128_load_schedule_ossl(key, &schedule, 1);
206 | TIME_OPERATION_SECONDS(oqs_aes128_ecb_enc_sch_ossl(plaintext, 320, schedule, ciphertext), "oqs_aes128_ecb_enc_sch_ossl", BENCH_DURATION);
207 | oqs_aes128_load_schedule_ossl(key, &schedule, 0);
208 | TIME_OPERATION_SECONDS(oqs_aes128_ecb_dec_sch_ossl(ciphertext, 320, schedule, plaintext), "oqs_aes128_ecb_dec_sch_ossl", BENCH_DURATION);
209 | }
210 | #endif
211 |
212 | int main(int argc, char **argv) {
213 | int ret;
214 | bool bench = false;
215 |
216 | for (int i = 1; i < argc; i++) {
217 | if (argv[i][0] == '-') {
218 | if (strcmp(argv[i], "--bench") == 0 || strcmp(argv[i], "-b") == 0) {
219 | bench = true;
220 | } else {
221 | printf("Usage: ./test_rand [options]\n");
222 | printf("\nOptions:\n");
223 | printf(" --bench, -b\n");
224 | printf(" Run benchmarks\n");
225 | if ((strcmp(argv[i], "-h") == 0) || (strcmp(argv[i], "-help") == 0) || (strcmp(argv[i], "--help") == 0)) {
226 | return EXIT_SUCCESS;
227 | } else {
228 | return EXIT_FAILURE;
229 | }
230 | }
231 | }
232 | }
233 |
234 | printf("=== test_aes correctness ===\n");
235 | OQS_RAND *rand = OQS_RAND_new(OQS_RAND_alg_default);
236 | if (rand == NULL) {
237 | fprintf(stderr, "OQS_RAND_new() failed\n");
238 | goto err;
239 | }
240 | TEST_REPEATEDLY(test_aes128_correctness_c(rand));
241 | #ifdef AES_ENABLE_NI
242 | TEST_REPEATEDLY(test_aes128_correctness_ni(rand));
243 | TEST_REPEATEDLY(test_aes128_c_equals_ni(rand));
244 | #endif
245 | TEST_REPEATEDLY(test_aes128_ecb_correctness_c(rand));
246 | #ifdef AES_ENABLE_NI
247 | TEST_REPEATEDLY(test_aes128_ecb_correctness_ni(rand));
248 | #endif
249 | #ifdef USE_OPENSSL
250 | TEST_REPEATEDLY(test_aes128_ecb_correctness_ossl(rand));
251 | #endif
252 | printf("Tests passed.\n\n");
253 |
254 | if (bench) {
255 | printf("=== test_aes performance ===\n");
256 | PRINT_TIMER_HEADER
257 | speed_aes128_c(rand);
258 | #ifdef AES_ENABLE_NI
259 | speed_aes128_ni(rand);
260 | #endif
261 | #ifdef USE_OPENSSL
262 | speed_aes128_ossl(rand);
263 | #endif
264 | PRINT_TIMER_FOOTER
265 | }
266 |
267 | ret = EXIT_SUCCESS;
268 | goto cleanup;
269 | err:
270 | ret = EXIT_FAILURE;
271 | cleanup:
272 | OQS_RAND_free(rand);
273 | return ret;
274 | }
275 |
--------------------------------------------------------------------------------
/src/frodo.h:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * Frodo: a post-quantum key exchange based on the Learning with Errors (LWE) problem.
3 | *
4 | * Abstract: header for settings
5 | *********************************************************************************************/
6 |
7 | #ifndef __FRODO_H
8 | #define __FRODO_H
9 |
10 | #include
11 | #include
12 |
13 |
14 | // Definition of operating system
15 |
16 | #define OS_WIN 1
17 | #define OS_LINUX 2
18 |
19 | #if defined(WINDOWS) // Microsoft Windows
20 | #define OS_TARGET OS_WIN
21 | #elif defined(LINUX) // Linux
22 | #define OS_TARGET OS_LINUX
23 | #else
24 | #error -- "Unsupported OS"
25 | #endif
26 |
27 |
28 | // Definition of compiler
29 |
30 | #define COMPILER_VC 1
31 | #define COMPILER_GCC 2
32 | #define COMPILER_CLANG 3
33 |
34 | #if defined(_MSC_VER) // Microsoft Visual C compiler
35 | #define COMPILER COMPILER_VC
36 | #elif defined(__GNUC__) // GNU GCC compiler
37 | #define COMPILER COMPILER_GCC
38 | #elif defined(__clang__) // Clang compiler
39 | #define COMPILER COMPILER_CLANG
40 | #else
41 | #error -- "Unsupported COMPILER"
42 | #endif
43 |
44 |
45 | // Definition of the targeted architecture and basic data types
46 |
47 | #define TARGET_AMD64 1
48 | #define TARGET_x86 2
49 | #define TARGET_ARM 3
50 |
51 | #if defined(_AMD64_)
52 | #define TARGET TARGET_AMD64
53 | #elif defined(_X86_)
54 | #define TARGET TARGET_x86
55 | #elif defined(_ARM_)
56 | #define TARGET TARGET_ARM
57 | #else
58 | #error -- "Unsupported ARCHITECTURE"
59 | #endif
60 |
61 |
62 | #if defined(WINDOWS)
63 | #define ALIGN_HEADER(N) __declspec(align(N))
64 | #define ALIGN_FOOTER(N)
65 | #else
66 | #define ALIGN_HEADER(N)
67 | #define ALIGN_FOOTER(N) __attribute__((aligned(N)))
68 | #endif
69 |
70 |
71 | #if defined(AVX2)
72 | #define USE_AVX2
73 | #endif
74 |
75 |
76 | #endif
77 |
--------------------------------------------------------------------------------
/src/frodo_macrify.h:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * Frodo: a post-quantum key exchange based on the Learning with Errors (LWE) problem.
3 | *
4 | * Abstract: header for functions with parameter-specific instantiations
5 | *********************************************************************************************/
6 |
7 | #ifndef _FRODO_MACRIFY_H_
8 | #define _FRODO_MACRIFY_H_
9 |
10 | #include
11 | #include "frodo.h"
12 | #include "random/rand.h"
13 |
14 |
15 | struct oqs_kex_lwe_frodo_params {
16 | uint8_t *seed;
17 | size_t seed_len;
18 | char *param_name;
19 | uint8_t log2_q;
20 | uint16_t q;
21 | uint16_t n;
22 | uint16_t extracted_bits;
23 | uint16_t nbar;
24 | uint16_t key_bits;
25 | uint16_t rec_hint_len;
26 | //uint16_t aux_len; //////////// FOR FRODOSIMPLE
27 | uint32_t pub_len;
28 | uint16_t stripe_step;
29 | int sampler_num;
30 | uint16_t *cdf_table;
31 | size_t cdf_table_len;
32 | };
33 |
34 | void oqs_kex_lwe_frodo_crossround2_recommended(unsigned char *out, const uint16_t *in);
35 | void oqs_kex_lwe_frodo_round2_recommended(unsigned char *out, uint16_t *in);
36 | void oqs_kex_lwe_frodo_reconcile_recommended(unsigned char *out, uint16_t *w, const unsigned char *hint);
37 |
38 | void oqs_kex_lwe_frodo_key_round(uint16_t *vec, const size_t length, const int b);
39 | void oqs_kex_lwe_frodo_key_round_hints(uint16_t *vec, const size_t length, const int b, const unsigned char *hint);
40 | void oqs_kex_lwe_frodo_pack(unsigned char *out, const size_t outlen, const uint16_t *in, const size_t inlen, const unsigned char lsb);
41 | void oqs_kex_lwe_frodo_unpack(uint16_t *out, const size_t outlen, const unsigned char *in, const size_t inlen, const unsigned char lsb);
42 | int oqs_kex_lwe_frodo_sample_n(uint16_t *s, const size_t n, struct oqs_kex_lwe_frodo_params *params, OQS_RAND *rand);
43 |
44 | int oqs_kex_lwe_frodo_mul_add_as_plus_e_on_the_fly_recommended(uint16_t *b, const uint16_t *s, const uint16_t *e, struct oqs_kex_lwe_frodo_params *params);
45 | int oqs_kex_lwe_frodo_mul_add_sa_plus_e_on_the_fly_recommended(uint16_t *b, const uint16_t *s, const uint16_t *e, struct oqs_kex_lwe_frodo_params *params);
46 | void oqs_kex_lwe_frodo_mul_add_sb_plus_e_recommended(uint16_t *out, const uint16_t *b, const uint16_t *s, const uint16_t *e);
47 | void oqs_kex_lwe_frodo_mul_bs_recommended(uint16_t *out, const uint16_t *b, const uint16_t *s);
48 |
49 |
50 | #endif
51 |
--------------------------------------------------------------------------------
/src/kex.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include "kex.h"
3 | #include "kex_lwe_frodo.h"
4 |
5 |
6 | OQS_KEX *OQS_KEX_new(OQS_RAND *rand, enum OQS_KEX_alg_name alg_name, const uint8_t *seed, const size_t seed_len, const char *named_parameters) {
7 | switch (alg_name) {
8 | case OQS_KEX_alg_default:
9 | case OQS_KEX_alg_lwe_frodo:
10 | return OQS_KEX_lwe_frodo_new(rand, seed, seed_len, named_parameters);
11 | default:
12 | assert(0);
13 | return NULL;
14 | }
15 | }
16 |
17 |
18 | int OQS_KEX_alice_0(OQS_KEX *k, void **alice_priv, uint8_t **alice_msg, size_t *alice_msg_len) {
19 | if (k == NULL) {
20 | return 0;
21 | } else {
22 | return k->alice_0(k, alice_priv, alice_msg, alice_msg_len);
23 | }
24 | }
25 |
26 |
27 | int OQS_KEX_bob(OQS_KEX *k, const uint8_t *alice_msg, const size_t alice_msg_len, uint8_t **bob_msg, size_t *bob_msg_len, uint8_t **key, size_t *key_len) {
28 | if (k == NULL) {
29 | return 0;
30 | } else {
31 | return k->bob(k, alice_msg, alice_msg_len, bob_msg, bob_msg_len, key, key_len);
32 | }
33 | }
34 |
35 |
36 | int OQS_KEX_alice_1(OQS_KEX *k, const void *alice_priv, const uint8_t *bob_msg, const size_t bob_msg_len, uint8_t **key, size_t *key_len) {
37 | if (k == NULL) {
38 | return 0;
39 | } else {
40 | return k->alice_1(k, alice_priv, bob_msg, bob_msg_len, key, key_len);
41 | }
42 | }
43 |
44 |
45 | void OQS_KEX_alice_priv_free(OQS_KEX *k, void *alice_priv) {
46 | if (k) {
47 | k->alice_priv_free(k, alice_priv);
48 | }
49 | }
50 |
51 |
52 | void OQS_KEX_free(OQS_KEX *k) {
53 | if (k) {
54 | k->free(k);
55 | }
56 | }
--------------------------------------------------------------------------------
/src/kex.h:
--------------------------------------------------------------------------------
1 | /**
2 | * \file kex.h
3 | * \brief Header defining the API for generic OQS Key exchange
4 | */
5 |
6 | #ifndef __OQS_KEX_H
7 | #define __OQS_KEX_H
8 |
9 | #include
10 | #include
11 | #include "frodo.h"
12 | #include "random/rand.h"
13 |
14 |
15 | enum OQS_KEX_alg_name {
16 | OQS_KEX_alg_default,
17 | OQS_KEX_alg_lwe_frodo,
18 | };
19 |
20 | typedef struct OQS_KEX OQS_KEX;
21 |
22 | /**
23 | * OQS key exchange object
24 | */
25 | typedef struct OQS_KEX {
26 | OQS_RAND *rand; // PRNG
27 | char *method_name; // Specifies the name of the key exchange method.
28 | uint16_t estimated_classical_security; // Classical security in terms of the number of bits provided by the key exchange method.
29 | uint16_t estimated_quantum_security; // Equivalent quantum security in terms of the number of bits provided by the key exchange method.
30 | uint8_t *seed; // An instance-specific seed, if any.
31 | size_t seed_len; // Size of instance-specific seed, if any.
32 | char *named_parameters; // Named parameters for this key exchange method instance, if any.
33 | void *params; // Opaque pointer for passing around instance-specific data.
34 | void *ctx; // Opaque pointer for passing around any computation context.
35 |
36 | /**
37 | * Pointer to a function for public and private key generation by Alice.
38 | *
39 | * @param k Key exchange structure
40 | * @param alice_priv Alice's private key
41 | * @param alice_msg Alice's message (public key + optional additional data)
42 | * @param alice_msg_len Alice's message length
43 | * @return 1 on success, or 0 on failure
44 | */
45 | int (*alice_0)(OQS_KEX *k, void **alive_priv, uint8_t **alice_msg, size_t *alice_msg_len);
46 |
47 | /**
48 | * Pointer to a function for shared key generation by Bob.
49 | *
50 | * @param k Key exchange structure
51 | * @param alice_msg Alice's message (public key + optional additional data)
52 | * @param alice_msg_len Alice's message length
53 | * @param bob_msg Bob's message (public key / encryption of shared key + optional additional data)
54 | * @param bob_msg_len Bob's message length
55 | * @param key Shared key
56 | * @param key_len Shared key length
57 | * @return 1 on success, or 0 on failure
58 | */
59 | int (*bob)(OQS_KEX *k, const uint8_t *alice_msg, const size_t alice_msg_len, uint8_t **bob_msg, size_t *bob_msg_len, uint8_t **key, size_t *key_len);
60 |
61 | /**
62 | * Pointer to a function for shared key generation by Alice.
63 | *
64 | * @param k Key exchange structure
65 | * @param alice_priv Alice's private key
66 | * @param bob_msg Bob's message (public key / encryption of shared key + optional additional data)
67 | * @param bob_msg_len Bob's message length
68 | * @param key Shared key
69 | * @param key_len Shared key length
70 | * @return 1 on success, or 0 on failure
71 | */
72 | int (*alice_1)(OQS_KEX *k, const void *alice_priv, const uint8_t *bob_msg, const size_t bob_msg_len, uint8_t **key, size_t *key_len);
73 |
74 | /**
75 | * Pointer to a function for freeing Alice's private key
76 | *
77 | * @param k Key exchange structure
78 | * @param alice_priv Alice's private key
79 | */
80 | void (*alice_priv_free)(OQS_KEX *k, void *alice_priv);
81 |
82 | /**
83 | * Pointer to a function for freeing the allocated key exchange structure
84 | *
85 | * @param k Key exchange structure
86 | */
87 | void (*free)(OQS_KEX *k);
88 |
89 | } OQS_KEX;
90 |
91 |
92 | /**
93 | * Allocate a new key exchange object.
94 | *
95 | * @param rand Random number generator.
96 | * @param alg_name Algorithm to be instantiated
97 | * @param seed An instance-specific seed, if any, or NULL.
98 | * @param seed_len The length of seed, or 0.
99 | * @param named_parameters Name or description of method-specific parameters
100 | * to use for this instance (as a NULL-terminated C string),
101 | * if any, or NULL.
102 | * @return The object on success, or NULL on failure.
103 | */
104 | OQS_KEX *OQS_KEX_new(OQS_RAND *rand, enum OQS_KEX_alg_name alg_name, const uint8_t *seed, const size_t seed_len, const char *named_parameters);
105 |
106 | int OQS_KEX_alice_0(OQS_KEX *k, void **alice_priv, uint8_t **alice_msg, size_t *alice_msg_len);
107 | int OQS_KEX_bob(OQS_KEX *k, const uint8_t *alice_msg, const size_t alice_msg_len, uint8_t **bob_msg, size_t *bob_msg_len, uint8_t **key, size_t *key_len);
108 | int OQS_KEX_alice_1(OQS_KEX *k, const void *alice_priv, const uint8_t *bob_msg, const size_t bob_msg_len, uint8_t **key, size_t *key_len);
109 |
110 | void OQS_KEX_alice_priv_free(OQS_KEX *k, void *alice_priv);
111 | void OQS_KEX_free(OQS_KEX *k);
112 |
113 | #endif
114 |
--------------------------------------------------------------------------------
/src/kex_lwe_frodo.c:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * Frodo: a post-quantum key exchange based on the Learning with Errors (LWE) problem.
3 | *
4 | * Abstract: key exchange
5 | * Instantiates "kex_lwe_frodo_macrify.c" with the necessary kex functions
6 | *********************************************************************************************/
7 |
8 | #if defined(WINDOWS)
9 | #define UNUSED
10 | #else
11 | #define UNUSED __attribute__ ((unused))
12 | #endif
13 |
14 | #include
15 | #include
16 | #if !defined(WINDOWS)
17 | #include
18 | #include
19 | #endif
20 |
21 | #include "kex.h"
22 | #include "random/rand.h"
23 | #include "kex_lwe_frodo.h"
24 | #include "frodo_macrify.h"
25 |
26 | #if defined(USE_AVX2)
27 | #if defined(WINDOWS)
28 | #include
29 | #else
30 | #include
31 | #endif
32 | #endif
33 |
34 | #define LWE_DIV_ROUNDUP(x, y) (((x) + (y)-1) / y)
35 |
36 |
37 | OQS_KEX *OQS_KEX_lwe_frodo_new(OQS_RAND *rand, const uint8_t *seed, const size_t seed_len, const char *named_parameters)
38 | { // Create a new Frodo structure
39 | OQS_KEX *k;
40 | struct oqs_kex_lwe_frodo_params *params;
41 |
42 | if ((seed_len == 0) || (seed == NULL)) {
43 | return NULL;
44 | }
45 |
46 | k = malloc(sizeof(OQS_KEX));
47 | if (k == NULL) {
48 | goto err;
49 | }
50 | k->named_parameters = NULL;
51 | k->method_name = NULL;
52 |
53 | k->params = malloc(sizeof(struct oqs_kex_lwe_frodo_params));
54 | if (NULL == k->params) {
55 | goto err;
56 | }
57 | params = (struct oqs_kex_lwe_frodo_params*)k->params;
58 | params->cdf_table = NULL;
59 | params->seed = NULL;
60 | params->param_name = NULL;
61 |
62 | k->rand = rand;
63 | k->ctx = NULL;
64 | k->alice_priv_free = &OQS_KEX_lwe_frodo_alice_priv_free;
65 | k->free = &OQS_KEX_lwe_frodo_free;
66 |
67 | if (strcmp(named_parameters, "recommended") == 0)
68 | {
69 | k->alice_0 = &OQS_KEX_lwe_frodo_alice_0_recommended;
70 | k->bob = &OQS_KEX_lwe_frodo_bob_recommended;
71 | k->alice_1 = &OQS_KEX_lwe_frodo_alice_1_recommended;
72 |
73 | k->method_name = strdup("LWE Frodo recommended");
74 | if (NULL == k->method_name) {
75 | goto err;
76 | }
77 | k->estimated_classical_security = 144;
78 | k->estimated_quantum_security = 130;
79 | k->named_parameters = strdup(named_parameters);
80 | if (k->named_parameters == NULL) {
81 | goto err;
82 | }
83 |
84 | params->seed = malloc(seed_len);
85 | if (NULL == params->seed) {
86 | goto err;
87 | }
88 | memcpy(params->seed, seed, seed_len);
89 | params->seed_len = seed_len;
90 | params->param_name = strdup("recommended");
91 | if (NULL == params->param_name) {
92 | goto err;
93 | }
94 | params->log2_q = 15;
95 | params->q = 1 << params->log2_q;
96 | params->n = 752;
97 | params->extracted_bits = 4;
98 | params->nbar = 8;
99 | params->key_bits = 256;
100 | params->rec_hint_len = LWE_DIV_ROUNDUP(params->nbar * params->nbar, 8);
101 | params->pub_len = LWE_DIV_ROUNDUP(params->n * params->nbar * params->log2_q, 8);
102 | params->stripe_step = 8;
103 | params->sampler_num = 12;
104 | params->cdf_table_len = 6;
105 | params->cdf_table = malloc(params->cdf_table_len * sizeof(uint16_t));
106 | if (NULL == params->cdf_table) {
107 | goto err;
108 | }
109 | uint16_t cdf_table_tmp[6] = {602, 1521, 1927, 2031, 2046, 2047};
110 | memcpy(params->cdf_table, cdf_table_tmp, sizeof(cdf_table_tmp));
111 | } else {
112 | goto err;
113 | }
114 |
115 | return k;
116 |
117 | err:
118 | if (k) {
119 | if (k->params) {
120 | free(params->cdf_table);
121 | free(params->seed);
122 | free(params->param_name);
123 | free(k->params);
124 | }
125 | free(k->named_parameters);
126 | free(k->method_name);
127 | free(k);
128 | }
129 | return NULL;
130 | }
131 |
132 |
133 | // Pre-process code to obtain "recommended" functions
134 | #define MACRIFY(NAME) NAME ## _recommended
135 | #define PARAMS_N 752
136 | #define PARAMS_NBAR 8
137 | #define PARAMS_EXTRACTED_BITS 4
138 | #include "kex_lwe_frodo_macrify.c"
139 | // Undefine macros to avoid any confusion later
140 | #undef PARAMS_N
141 | #undef PARAMS_NBAR
142 | #undef MACRIFY
143 |
144 |
145 | void OQS_KEX_lwe_frodo_alice_priv_free(UNUSED OQS_KEX *k, void *alice_priv)
146 | {
147 | if (alice_priv) {
148 | #if !defined(USE_AVX2)
149 | free(alice_priv);
150 | #else
151 | _mm_free(alice_priv);
152 | #endif
153 | }
154 | }
155 |
156 |
157 | void OQS_KEX_lwe_frodo_free(OQS_KEX *k)
158 | { // Free Frodo structure
159 | if (!k) {
160 | return;
161 | }
162 | if (k->params) {
163 | struct oqs_kex_lwe_frodo_params *params = (struct oqs_kex_lwe_frodo_params*)k->params;
164 | free(params->cdf_table);
165 | params->cdf_table = NULL;
166 | free(params->seed);
167 | params->seed = NULL;
168 | free(params->param_name);
169 | params->param_name = NULL;
170 | free(k->params);
171 | k->params = NULL;
172 | }
173 | free(k->named_parameters);
174 | k->named_parameters = NULL;
175 | free(k->method_name);
176 | k->method_name = NULL;
177 | free(k);
178 | }
179 |
--------------------------------------------------------------------------------
/src/kex_lwe_frodo.h:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * Frodo: a post-quantum key exchange based on the Learning with Errors (LWE) problem.
3 | *
4 | * Abstract: header for key exchange
5 | *********************************************************************************************/
6 |
7 | #ifndef __OQS_KEX_LWE_FRODO_H
8 | #define __OQS_KEX_LWE_FRODO_H
9 |
10 | #include
11 | #include
12 | #include "kex.h"
13 | #include "random/rand.h"
14 |
15 |
16 | OQS_KEX *OQS_KEX_lwe_frodo_new(OQS_RAND *rand, const uint8_t *seed, const size_t seed_len, const char *named_parameters);
17 | int OQS_KEX_lwe_frodo_alice_0_recommended(OQS_KEX *k, void **alice_priv, uint8_t **alice_msg, size_t *alice_msg_len);
18 | int OQS_KEX_lwe_frodo_bob_recommended(OQS_KEX *k, const uint8_t *alice_msg, const size_t alice_msg_len, uint8_t **bob_msg, size_t *bob_msg_len, uint8_t **key, size_t *key_len);
19 | int OQS_KEX_lwe_frodo_alice_1_recommended(OQS_KEX *k, const void *alice_priv, const uint8_t *bob_msg, const size_t bob_msg_len, uint8_t **key, size_t *key_len);
20 | void OQS_KEX_lwe_frodo_alice_priv_free(OQS_KEX *k, void *alice_priv);
21 | void OQS_KEX_lwe_frodo_free(OQS_KEX *k);
22 |
23 |
24 | #endif
25 |
--------------------------------------------------------------------------------
/src/kex_lwe_frodo_macrify.c:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * Frodo: a post-quantum key exchange based on the Learning with Errors (LWE) problem.
3 | *
4 | * Abstract: key exchange functions
5 | *********************************************************************************************/
6 |
7 |
8 | int MACRIFY(OQS_KEX_lwe_frodo_alice_0)(OQS_KEX *k, void **alice_priv, uint8_t **alice_msg, size_t *alice_msg_len)
9 | {
10 | int ret;
11 | struct oqs_kex_lwe_frodo_params *params = (struct oqs_kex_lwe_frodo_params*)k->params;
12 | uint16_t b[PARAMS_N * PARAMS_NBAR] = {0}, e[PARAMS_N * PARAMS_NBAR] = {0};
13 |
14 | *alice_priv = NULL;
15 | *alice_msg = NULL;
16 |
17 | // Allocate private key and outgoing message
18 | #if !defined(USE_AVX2)
19 | *alice_priv = malloc(params->n * params->nbar * sizeof(uint16_t));
20 | #else
21 | *alice_priv = _mm_malloc(params->n * params->nbar * sizeof(uint16_t), 32);
22 | #endif
23 | if (*alice_priv == NULL) {
24 | goto err;
25 | }
26 | *alice_msg = malloc(params->pub_len);
27 | if (*alice_msg == NULL) {
28 | goto err;
29 | }
30 |
31 | // Generate S and E
32 | ret = oqs_kex_lwe_frodo_sample_n(*alice_priv, params->n * params->nbar, params, k->rand);
33 | if (ret != 1) {
34 | goto err;
35 | }
36 | ret = oqs_kex_lwe_frodo_sample_n(e, params->n * params->nbar, params, k->rand);
37 | if (ret != 1) {
38 | goto err;
39 | }
40 |
41 | // Compute B = AS + E
42 | ret = MACRIFY(oqs_kex_lwe_frodo_mul_add_as_plus_e_on_the_fly)(b, *alice_priv, e, params);
43 | if (ret != 1) {
44 | goto err;
45 | }
46 | oqs_kex_lwe_frodo_pack(*alice_msg, params->pub_len, b, params->n * params->nbar, params->log2_q);
47 |
48 | *alice_msg_len = params->pub_len;
49 |
50 | ret = 1;
51 | return ret;
52 |
53 | err:
54 | ret = 0;
55 | free(*alice_msg);
56 | *alice_msg = NULL;
57 | free(*alice_priv);
58 | *alice_priv = NULL;
59 | return ret;
60 | }
61 |
62 |
63 | int MACRIFY(OQS_KEX_lwe_frodo_bob)(OQS_KEX *k, const uint8_t *alice_msg, const size_t alice_msg_len, uint8_t **bob_msg, size_t *bob_msg_len, uint8_t **key, size_t *key_len)
64 | {
65 | int ret;
66 | struct oqs_kex_lwe_frodo_params *params = (struct oqs_kex_lwe_frodo_params*)k->params;
67 | uint8_t *bob_rec = NULL;
68 | ALIGN_HEADER(32) uint16_t bob_priv[PARAMS_NBAR * PARAMS_N] ALIGN_FOOTER(32) = {0};
69 | ALIGN_HEADER(32) uint16_t b[PARAMS_NBAR * PARAMS_N] ALIGN_FOOTER(32) = {0};
70 | uint16_t bprime[PARAMS_NBAR * PARAMS_N] = {0};
71 | uint16_t eprime[PARAMS_NBAR * PARAMS_N] = {0};
72 | uint16_t eprimeprime[PARAMS_NBAR * PARAMS_NBAR] = {0};
73 | uint16_t v[PARAMS_NBAR * PARAMS_NBAR] = {0};
74 | *bob_msg = NULL;
75 | *key = NULL;
76 |
77 | // Check length of other party's public key
78 | if (alice_msg_len != params->pub_len) {
79 | goto err;
80 | }
81 |
82 | // Allocate outgoing message and key
83 | *bob_msg = malloc(params->pub_len + params->rec_hint_len);
84 | if (*bob_msg == NULL) {
85 | goto err;
86 | }
87 | bob_rec = *bob_msg + params->pub_len;
88 | *key = malloc(params->key_bits >> 3);
89 | if (*key == NULL) {
90 | goto err;
91 | }
92 |
93 | // Generate S' and E'
94 | ret = oqs_kex_lwe_frodo_sample_n(bob_priv, params->n * params->nbar, params, k->rand);
95 | if (ret != 1) {
96 | goto err;
97 | }
98 | ret = oqs_kex_lwe_frodo_sample_n(eprime, params->n * params->nbar, params, k->rand);
99 | if (ret != 1) {
100 | goto err;
101 | }
102 |
103 | // Compute B' = S'A + E'
104 | ret = MACRIFY(oqs_kex_lwe_frodo_mul_add_sa_plus_e_on_the_fly)(bprime, bob_priv, eprime, params);
105 | if (ret != 1) {
106 | goto err;
107 | }
108 | oqs_kex_lwe_frodo_pack(*bob_msg, params->pub_len, bprime, params->n * params->nbar, params->log2_q);
109 |
110 | // Generate E''
111 | ret = oqs_kex_lwe_frodo_sample_n(eprimeprime, params->nbar * params->nbar, params, k->rand);
112 | if (ret != 1) {
113 | goto err;
114 | }
115 |
116 | // Unpack B
117 | oqs_kex_lwe_frodo_unpack(b, params->n * params->nbar, alice_msg, alice_msg_len, params->log2_q);
118 |
119 | // Compute V = S'B + E''
120 | MACRIFY(oqs_kex_lwe_frodo_mul_add_sb_plus_e)(v, b, bob_priv, eprimeprime);
121 |
122 | // Compute C = _{2^B}
123 | MACRIFY(oqs_kex_lwe_frodo_crossround2)(bob_rec, v);
124 |
125 | // Compute K = round(V)_{2^B}
126 | MACRIFY(oqs_kex_lwe_frodo_round2)(*key, v);
127 |
128 | *bob_msg_len = params->pub_len + params->rec_hint_len;
129 | *key_len = params->key_bits >> 3;
130 |
131 | ret = 1;
132 | goto cleanup;
133 |
134 | err:
135 | ret = 0;
136 | free(*bob_msg);
137 | *bob_msg = NULL;
138 | if (*key != NULL) {
139 | memset(*key, 0, params->key_bits >> 3);
140 | }
141 | free(*key);
142 | *key = NULL;
143 |
144 | cleanup:
145 | memset(eprime, 0, PARAMS_NBAR * PARAMS_N * sizeof(uint16_t));
146 | memset(eprimeprime, 0, PARAMS_NBAR * PARAMS_NBAR * sizeof(uint16_t));
147 | memset(v, 0, PARAMS_NBAR * PARAMS_NBAR * sizeof(uint16_t));
148 | return ret;
149 | }
150 |
151 |
152 | int MACRIFY(OQS_KEX_lwe_frodo_alice_1)(OQS_KEX *k, const void *alice_priv, const uint8_t *bob_msg, const size_t bob_msg_len, uint8_t **key, size_t *key_len)
153 | {
154 | int ret;
155 | struct oqs_kex_lwe_frodo_params *params = (struct oqs_kex_lwe_frodo_params*)k->params;
156 | uint16_t *bprime = NULL, *w = NULL;
157 | //uint16_t bprime[PARAMS_NBAR * PARAMS_N] = {0};
158 | //uint16_t w[PARAMS_NBAR * PARAMS_NBAR] = {0};
159 | *key = NULL;
160 |
161 | // Check length of other party's public key
162 | if (bob_msg_len != params->pub_len + params->rec_hint_len) {
163 | goto err;
164 | }
165 |
166 | // Allocate working values and session key
167 | bprime = malloc(params->n * params->nbar * sizeof(uint16_t));
168 | if (bprime == NULL) {
169 | goto err;
170 | }
171 | w = malloc(params->nbar * params->nbar * sizeof(uint16_t));
172 | if (w == NULL) {
173 | goto err;
174 | }
175 | *key = malloc(params->key_bits >> 3);
176 | if (*key == NULL) {
177 | goto err;
178 | }
179 |
180 | // Unpack B'
181 | oqs_kex_lwe_frodo_unpack(bprime, params->n * params->nbar, bob_msg, params->pub_len, params->log2_q);
182 |
183 | // Compute W = B'S
184 | MACRIFY(oqs_kex_lwe_frodo_mul_bs)(w, bprime, (uint16_t*)alice_priv);
185 |
186 | // Compute K = rec(B'S, C)
187 | const uint8_t *bob_rec = bob_msg + params->pub_len;
188 | MACRIFY(oqs_kex_lwe_frodo_reconcile)(*key, w, bob_rec);
189 |
190 | *key_len = params->key_bits >> 3;
191 |
192 | ret = 1;
193 | goto cleanup;
194 | //goto exit;
195 |
196 | err:
197 | ret = 0;
198 | memset(key, 0, params->key_bits >> 3);
199 | free(*key);
200 | *key = NULL;
201 |
202 | cleanup:
203 | free(w);
204 | free(bprime);
205 |
206 | //exit:
207 | return ret;
208 | }
--------------------------------------------------------------------------------
/src/lwe.c:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * Frodo: a post-quantum key exchange based on the Learning with Errors (LWE) problem.
3 | *
4 | * Abstract: functions for the kex scheme
5 | * Instantiates "lwe_macrify.c" with the necessary matrix arithmetic functions
6 | *********************************************************************************************/
7 |
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include "frodo_macrify.h"
14 |
15 | #define min(x, y) (((x) < (y)) ? (x) : (y))
16 |
17 |
18 | void oqs_kex_lwe_frodo_key_round(uint16_t *vec, const size_t length, const int b)
19 | { // Round all elements of a vector to the nearest multiple of 2^b
20 | size_t i;
21 | uint16_t negmask = ~((1 << b) - 1);
22 | uint16_t half = b > 0 ? 1 << (b - 1) : 0;
23 |
24 | for (i = 0; i < length; i++) {
25 | vec[i] = (vec[i] + half) & negmask;
26 | }
27 | }
28 |
29 |
30 | void oqs_kex_lwe_frodo_key_round_hints(uint16_t *vec, const size_t length, const int b, const unsigned char *hint)
31 | { // Round all elements of a vector to the multiple of 2^b, with a hint for the direction of rounding when close to the boundary.
32 | size_t i;
33 | uint16_t whole = 1 << b;
34 | uint16_t mask = whole - 1;
35 | uint16_t negmask = ~mask;
36 | uint16_t half = 1 << (b - 1);
37 | uint16_t quarter = 1 << (b - 2);
38 |
39 | for (i = 0; i < length; i++) {
40 | uint16_t remainder = vec[i] & mask;
41 | uint16_t use_hint = ((remainder + quarter) >> (b - 1)) & 0x1;
42 |
43 | unsigned char h = (hint[i / 8] >> (i % 8)) % 2; // the hint
44 | uint16_t shift = use_hint * (2 * h - 1) * quarter;
45 |
46 | // If use_hint = 1 and h = 0, adding -quarter forces rounding down
47 | // h = 1, adding quarter forces rounding up
48 |
49 | vec[i] = (vec[i] + half + shift) & negmask;
50 | }
51 | }
52 |
53 |
54 | void oqs_kex_lwe_frodo_pack(unsigned char *out, const size_t outlen, const uint16_t *in, const size_t inlen, const unsigned char lsb)
55 | { // Pack the input uint16 vector into a char output vector, copying lsb bits from each input element.
56 | // If inlen * lsb / 8 > outlen, only outlen * 8 bits are copied.
57 | memset(out, 0, outlen);
58 |
59 | size_t i = 0; // whole bytes already filled in
60 | size_t j = 0; // whole uint16_t already copied
61 | uint16_t w = 0; // the leftover, not yet copied
62 | unsigned char bits = 0; // the number of lsb in w
63 |
64 | while (i < outlen && (j < inlen || ((j == inlen) && (bits > 0)))) {
65 | /*
66 | in: | | |********|********|
67 | ^
68 | j
69 | w : | ****|
70 | ^
71 | bits
72 | out:|**|**|**|**|**|**|**|**|* |
73 | ^^
74 | ib
75 | */
76 | unsigned char b = 0; // bits in out[i] already filled in
77 | while (b < 8) {
78 | int nbits = min(8 - b, bits);
79 | uint16_t mask = (1 << nbits) - 1;
80 | unsigned char t = (w >> (bits - nbits)) & mask; // the bits to copy from w to out
81 | out[i] = out[i] + (t << (8 - b - nbits));
82 | b += nbits;
83 | bits -= nbits;
84 | w &= ~(mask << bits); // not strictly necessary; mostly for debugging
85 |
86 | if (bits == 0) {
87 | if (j < inlen) {
88 | w = in[j];
89 | bits = lsb;
90 | j++;
91 | } else {
92 | break; // the input vector is exhausted
93 | }
94 | }
95 | }
96 | if (b == 8) { // out[i] is filled in
97 | i++;
98 | }
99 | }
100 | }
101 |
102 |
103 | void oqs_kex_lwe_frodo_unpack(uint16_t *out, const size_t outlen, const unsigned char *in, const size_t inlen, const unsigned char lsb)
104 | { // Unpack the input char vector into a uint16_t output vector, copying lsb bits
105 | // for each output element from input. outlen must be at least ceil(inlen * 8 / lsb).
106 | memset(out, 0, outlen * sizeof(uint16_t));
107 |
108 | size_t i = 0; // whole uint16_t already filled in
109 | size_t j = 0; // whole bytes already copied
110 | unsigned char w = 0; // the leftover, not yet copied
111 | unsigned char bits = 0; // the number of lsb bits of w
112 |
113 | while (i < outlen && (j < inlen || ((j == inlen) && (bits > 0)))) {
114 | /*
115 | in: | | | | | | |**|**|...
116 | ^
117 | j
118 | w : | *|
119 | ^
120 | bits
121 | out:| *****| *****| *** | |...
122 | ^ ^
123 | i b
124 | */
125 | unsigned char b = 0; // bits in out[i] already filled in
126 | while (b < lsb) {
127 | int nbits = min(lsb - b, bits);
128 | uint16_t mask = (1 << nbits) - 1;
129 | unsigned char t = (w >> (bits - nbits)) & mask; // the bits to copy from w to out
130 | out[i] = out[i] + (t << (lsb - b - nbits));
131 | b += nbits;
132 | bits -= nbits;
133 | w &= ~(mask << bits); // not strictly necessary; mostly for debugging
134 |
135 | if (bits == 0) {
136 | if (j < inlen) {
137 | w = in[j];
138 | bits = 8;
139 | j++;
140 | } else {
141 | break; // the input vector is exhausted
142 | }
143 | }
144 | }
145 | if (b == lsb) { // out[i] is filled in
146 | i++;
147 | }
148 | }
149 | }
150 |
151 |
152 | #define LWE_DIV_ROUNDUP(x, y) (((x) + (y)-1) / y)
153 |
154 | // Define parameters for "recommended" parameter set
155 | #define PARAMS_N 752
156 | #define PARAMS_NBAR 8
157 | #define PARAMS_LOG2Q 15
158 | #define PARAMS_Q (1 << PARAMS_LOG2Q)
159 | #define PARAMS_EXTRACTED_BITS 4
160 | #define PARAMS_SWITCH_MODULUS (PARAMS_LOG2Q-PARAMS_EXTRACTED_BITS-1)
161 | #define PARAMS_KEY_BITS 256
162 | #define PARAMS_STRIPE_STEP 8
163 | #define PARAMS_REC_HINT_LENGTH LWE_DIV_ROUNDUP(PARAMS_NBAR * PARAMS_NBAR, 8)
164 | #define PARAMS_PARALLEL 4
165 | // Pre-process code to obtain "recommended" functions
166 | #define MACRIFY(NAME) NAME ## _recommended
167 |
168 | #if defined(REFERENCE)
169 | #include "lwe_macrify_reference.c"
170 | #else
171 | #include "lwe_macrify.c"
172 | #endif
173 |
174 | // Undefine macros to avoid any confusion later
175 | #undef PARAMS_N
176 | #undef PARAMS_NBAR
177 | #undef PARAMS_LOG2Q
178 | #undef PARAMS_Q
179 | #undef PARAMS_EXTRACTED_BITS
180 | #undef PARAMS_KEY_BITS
181 | #undef PARAMS_STRIPE_STEP
182 | #undef PARAMS_REC_HINT_LENGTH
183 | #undef PARAMS_PARALLEL
184 | #undef MACRIFY
185 |
--------------------------------------------------------------------------------
/src/lwe_macrify_reference.c:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * Frodo: a post-quantum key exchange based on the Learning with Errors (LWE) problem.
3 | *
4 | * Abstract: matrix arithmetic functions required by the kex scheme
5 | *********************************************************************************************/
6 |
7 | //#define AES128_ECB
8 |
9 | #include "malloc.h"
10 | #if defined(AES128_ECB)
11 | #include "aes/aes.h"
12 | #else
13 | #include "sha3/fips202.h"
14 | #endif
15 |
16 |
17 | int MACRIFY(oqs_kex_lwe_frodo_mul_add_as_plus_e_on_the_fly)(uint16_t *out, const uint16_t *s, const uint16_t *e, struct oqs_kex_lwe_frodo_params *params)
18 | { // Generate-and-multiply: generate matrix A (N x N) row-wise, multiply by s on the right.
19 | // Inputs: s, e (N x N_BAR)
20 | // Output: out = A*s + e (N x N_BAR)
21 | int i, j, k;
22 | int ret = 0;
23 | int16_t* A = NULL;
24 | size_t A_len = PARAMS_N * PARAMS_N * sizeof(int16_t);
25 |
26 | A = calloc(1, A_len);
27 | if (A == NULL) {
28 | return ret;
29 | }
30 |
31 | #if defined(AES128_ECB) // Matrix A generation using AES128-ECB, done per 128-bit block
32 | for (i = 0; i < PARAMS_N; i++) {
33 | for (j = 0; j < PARAMS_N; j += PARAMS_STRIPE_STEP) {
34 | A[i*PARAMS_N + j] = i; // Loading values in the little-endian order
35 | A[i*PARAMS_N + j + 1] = j;
36 | }
37 | }
38 |
39 | assert(params->seed_len == 16);
40 | void *aes_key_schedule = NULL;
41 | OQS_AES128_load_schedule(params->seed, &aes_key_schedule, 1);
42 | OQS_AES128_ECB_enc_sch((uint8_t*)A, A_len, aes_key_schedule, (uint8_t*)A);
43 | #else // Matrix A generation using cSHAKE128, done per 16*N-bit row
44 | for (i = 0; i < PARAMS_N; i++) {
45 | cshake128_simple((unsigned char*)(A + i*PARAMS_N), (unsigned long long)(2*PARAMS_N), (uint16_t)i, params->seed, (unsigned long long)params->seed_len);
46 | }
47 | #endif
48 | memcpy(out, e, PARAMS_NBAR * PARAMS_N * sizeof(uint16_t));
49 |
50 | for (i = 0; i < PARAMS_N; i++) { // Matrix multiplication-addition A*s + e
51 | for (k = 0; k < PARAMS_NBAR; k++) {
52 | uint16_t sum = 0;
53 | for (j = 0; j < PARAMS_N; j++) {
54 | sum += A[i*PARAMS_N + j] * s[j*PARAMS_NBAR + k];
55 | }
56 | out[i*PARAMS_NBAR + k] += sum; // Adding e. No need to reduce modulo 2^15, extra bits are taken care of during packing later on.
57 | }
58 | }
59 |
60 | #if defined(AES128_ECB)
61 | OQS_AES128_free_schedule(aes_key_schedule);
62 | #endif
63 | return 1;
64 | }
65 |
66 |
67 | int MACRIFY(oqs_kex_lwe_frodo_mul_add_sa_plus_e_on_the_fly)(uint16_t *out, const uint16_t *s, const uint16_t *e, struct oqs_kex_lwe_frodo_params *params)
68 | { // Generate-and-multiply: generate matrix A (N x N) column-wise, multiply by s' on the left.
69 | // Inputs: s', e' (N_BAR x N)
70 | // Output: out = s'*A + e' (N_BAR x N)
71 | int i, j, k;
72 | int ret = 0;
73 | int16_t* A = NULL;
74 | size_t A_len = PARAMS_N * PARAMS_N * sizeof(int16_t);
75 |
76 | A = calloc(1, A_len);
77 | if (A == NULL) {
78 | return ret;
79 | }
80 |
81 | #if defined(AES128_ECB) // Matrix A generation using AES128-ECB, done per 128-bit block
82 | for (i = 0; i < PARAMS_N; i++) {
83 | for (j = 0; j < PARAMS_N; j += PARAMS_STRIPE_STEP) {
84 | A[i*PARAMS_N + j] = i; // Loading values in the little-endian order
85 | A[i*PARAMS_N + j + 1] = j;
86 | }
87 | }
88 |
89 | assert(params->seed_len == 16);
90 | void *aes_key_schedule = NULL;
91 | OQS_AES128_load_schedule(params->seed, &aes_key_schedule, 1);
92 | OQS_AES128_ECB_enc_sch((uint8_t*)A, A_len, aes_key_schedule, (uint8_t*)A);
93 | #else // Matrix A generation using cSHAKE128, done per 16*N-bit row
94 | for (i = 0; i < PARAMS_N; i++) {
95 | cshake128_simple((unsigned char*)(A + i*PARAMS_N), (unsigned long long)(2*PARAMS_N), (uint16_t)i, params->seed, (unsigned long long)params->seed_len);
96 | }
97 | #endif
98 | memcpy(out, e, PARAMS_NBAR * PARAMS_N * sizeof(uint16_t));
99 |
100 | for (i = 0; i < PARAMS_N; i++) { // Matrix multiplication-addition A*s + e
101 | for (k = 0; k < PARAMS_NBAR; k++) {
102 | uint16_t sum = 0;
103 | for (j = 0; j < PARAMS_N; j++) {
104 | sum += A[j*PARAMS_N + i] * s[k*PARAMS_N + j];
105 | }
106 | out[k*PARAMS_N + i] += sum; // Adding e. No need to reduce modulo 2^15, extra bits are taken care of during packing later on.
107 | }
108 | }
109 |
110 | #if defined(AES128_ECB)
111 | OQS_AES128_free_schedule(aes_key_schedule);
112 | #endif
113 | return 1;
114 | }
115 |
116 |
117 | void MACRIFY(oqs_kex_lwe_frodo_mul_bs)(uint16_t *out, const uint16_t *b, const uint16_t *s)
118 | { // Multiply by s on the right
119 | // Inputs: b (N_BAR x N), s (N x N_BAR)
120 | // Output: out = b*s
121 | int i, j, k;
122 |
123 | for (i = 0; i < PARAMS_NBAR; i++) {
124 | for (j = 0; j < PARAMS_NBAR; j++) {
125 | out[i * PARAMS_NBAR + j] = 0;
126 | for (k = 0; k < PARAMS_N; k++) {
127 | out[i * PARAMS_NBAR + j] += b[i * PARAMS_N + k] * s[k*PARAMS_NBAR + j];
128 | }
129 | out[i * PARAMS_NBAR + j] = (uint32_t)(out[i * PARAMS_NBAR + j] << 17) >> 17; // Fixed to params->q = 1 << 15)
130 | }
131 | }
132 | }
133 |
134 |
135 | void MACRIFY(oqs_kex_lwe_frodo_mul_add_sb_plus_e)(uint16_t *out, const uint16_t *b, const uint16_t *s, const uint16_t *e)
136 | { // Multiply by s on the left
137 | // Inputs: b (N x N_BAR), s (N_BAR x N), e (N_BAR x N_BAR)
138 | // Output: out = s*b + e
139 | int i, j, k;
140 |
141 | for (k = 0; k < PARAMS_NBAR; k++) {
142 | for (i = 0; i < PARAMS_NBAR; i++) {
143 | out[k * PARAMS_NBAR + i] = e[k * PARAMS_NBAR + i];
144 | for (j = 0; j < PARAMS_N; j++) {
145 | out[k * PARAMS_NBAR + i] += s[k * PARAMS_N + j] * b[j * PARAMS_NBAR + i];
146 | }
147 | out[k * PARAMS_NBAR + i] = (uint32_t)(out[k * PARAMS_NBAR + i] << 17) >> 17; // Fixed to params->q = 1 << 15)
148 | }
149 | }
150 | }
151 |
152 |
153 | void MACRIFY(oqs_kex_lwe_frodo_add)(uint32_t *out, const uint32_t *a, const uint32_t *b)
154 | { // Add a and b
155 | // Inputs: a, b (N_BAR x N_BAR)
156 | // Output: c = a + b
157 |
158 | for (int i = 0; i < (PARAMS_NBAR * PARAMS_NBAR); i++) {
159 | out[i] = ((a[i] + b[i]) << 17) >> 17; // Fixed to params->q = 1 << 15
160 | }
161 | }
162 |
163 |
164 | void MACRIFY(oqs_kex_lwe_frodo_sub)(uint32_t *out, const uint32_t *a, const uint32_t *b)
165 | { // Subtract a and b
166 | // Inputs: a, b (N_BAR x N_BAR)
167 | // Output: c = a - b
168 |
169 | for (int i = 0; i < (PARAMS_NBAR * PARAMS_NBAR); i++) {
170 | out[i] = ((a[i] - b[i]) << 17) >> 17; // Fixed to params->q = 1 << 15
171 | }
172 | }
173 |
174 |
175 | void MACRIFY(oqs_kex_lwe_frodo_round2)(unsigned char *out, uint16_t *in)
176 | {
177 | oqs_kex_lwe_frodo_key_round(in, PARAMS_NBAR * PARAMS_NBAR, PARAMS_LOG2Q - PARAMS_EXTRACTED_BITS);
178 | int i;
179 |
180 | for (i = 0; i < PARAMS_NBAR * PARAMS_NBAR; i++) {
181 | in[i] >>= PARAMS_LOG2Q - PARAMS_EXTRACTED_BITS; // Drop bits that were zeroed out
182 | }
183 |
184 | // Out should have enough space for the key
185 | oqs_kex_lwe_frodo_pack(out, PARAMS_KEY_BITS / 8, in, PARAMS_NBAR * PARAMS_NBAR, PARAMS_EXTRACTED_BITS);
186 | }
187 |
188 |
189 | void MACRIFY(oqs_kex_lwe_frodo_crossround2)(unsigned char *out, const uint16_t *in)
190 | {
191 | int i;
192 | // Out should have enough space for N_BAR * N_BAR bits
193 | memset((unsigned char *)out, 0, PARAMS_REC_HINT_LENGTH);
194 |
195 | uint16_t whole = 1 << (PARAMS_LOG2Q - PARAMS_EXTRACTED_BITS);
196 | uint16_t half = whole >> 1;
197 | uint16_t mask = whole - 1;
198 |
199 | for (i = 0; i < PARAMS_NBAR * PARAMS_NBAR; i++) {
200 | uint16_t remainder = in[i] & mask;
201 | out[i / 8] += (remainder >= half) << (i % 8);
202 | }
203 | }
204 |
205 |
206 | void MACRIFY(oqs_kex_lwe_frodo_reconcile)(unsigned char *out, uint16_t *w, const unsigned char *hint)
207 | {
208 | oqs_kex_lwe_frodo_key_round_hints(w, PARAMS_NBAR * PARAMS_NBAR, PARAMS_LOG2Q - PARAMS_EXTRACTED_BITS, hint);
209 | int i;
210 |
211 | for (i = 0; i < PARAMS_NBAR * PARAMS_NBAR; i++) {
212 | w[i] >>= PARAMS_LOG2Q - PARAMS_EXTRACTED_BITS; // Drop bits that were zeroed out
213 | }
214 | oqs_kex_lwe_frodo_pack(out, PARAMS_KEY_BITS / 8, w, PARAMS_NBAR * PARAMS_NBAR, PARAMS_EXTRACTED_BITS);
215 | }
--------------------------------------------------------------------------------
/src/lwe_noise.c:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * Frodo: a post-quantum key exchange based on the Learning with Errors (LWE) problem.
3 | *
4 | * Abstract: sampling functions
5 | *********************************************************************************************/
6 |
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include "random/rand.h"
13 | #include "frodo_macrify.h"
14 |
15 |
16 | static int lwe_sample_n_inverse_8(uint16_t *s, const size_t n, const uint8_t *cdf_table, const size_t cdf_table_len, OQS_RAND *rand)
17 | { // Fills vector s with n samples from the noise distribution which requires 8 bits to sample. The distribution is specified by its CDF.
18 | // Super-constant timing: the CDF table is ingested for every sample.
19 | size_t rndlen = n;
20 | uint8_t *rndvec = (uint8_t *)malloc(rndlen);
21 |
22 | if (rndvec == NULL) {
23 | fprintf(stderr, "malloc failure\n");
24 | return 0;
25 | }
26 | OQS_RAND_n(rand, rndvec, rndlen);
27 |
28 | size_t i, j;
29 |
30 | for (i = 0; i < n; ++i) {
31 | uint8_t sample = 0;
32 | uint8_t rnd = rndvec[i] >> 1; // Drop the least significant bit
33 | uint8_t sign = rndvec[i] & 0x1; // Pick the least significant bit
34 |
35 | // No need to compare with the last value.
36 | for (j = 0; j < cdf_table_len - 1; j++) {
37 | // Constant time comparison: 1 if cdf_table[j] < rnd, 0 otherwise.
38 | // Critically uses the fact that cdf_table[j] and rnd fit in 7 bits.
39 | sample += (uint8_t)(cdf_table[j] - rnd) >> 7;
40 | }
41 | // Assuming that sign is either 0 or 1, flips sample iff sign = 1
42 | s[i] = ((-sign) ^ sample) + sign;
43 | }
44 |
45 | memset(rndvec, 0, rndlen);
46 | free(rndvec);
47 | return 1;
48 | }
49 |
50 |
51 | static int lwe_sample_n_inverse_12(uint16_t *s, const size_t n, const uint16_t *cdf_table, const size_t cdf_table_len, OQS_RAND *rand)
52 | { // Fills vector s with n samples from the noise distribution which requires 12 bits to sample. The distribution is specified by its CDF.
53 | // Super-constant timing: the CDF table is ingested for every sample.
54 | size_t rndlen = 3 * ((n + 1) / 2); // 12 bits of unif randomness per output element
55 | uint8_t *rnd = (uint8_t *)malloc(rndlen);
56 |
57 | if (rnd == NULL) {
58 | fprintf(stderr, "malloc failure\n");
59 | return 0;
60 | }
61 | OQS_RAND_n(rand, rnd, rndlen);
62 |
63 | size_t i;
64 |
65 | for (i = 0; i < n; i += 2) { // two output elements at a time
66 | uint8_t *pRnd = (rnd + 3 * i / 2);
67 |
68 | uint16_t rnd1 = (((pRnd[0] << 8) + pRnd[1]) & 0xFFE0) >> 5; // first 11 bits (0..10)
69 | uint16_t rnd2 = (((pRnd[1] << 8) + pRnd[2]) & 0x1FFC) >> 2; // next 11 bits (11..21)
70 |
71 | uint8_t sample1 = 0;
72 | uint8_t sample2 = 0;
73 |
74 | size_t j;
75 | // No need to compare with the last value.
76 | for (j = 0; j < cdf_table_len - 1; j++) {
77 | // Constant time comparison: 1 if LWE_CDF_TABLE[j] < rnd1, 0 otherwise.
78 | // Critically uses the fact that LWE_CDF_TABLE[j] and rnd1 fit in 15 bits.
79 | sample1 += (uint16_t)(cdf_table[j] - rnd1) >> 15;
80 | sample2 += (uint16_t)(cdf_table[j] - rnd2) >> 15;
81 | }
82 |
83 | uint8_t sign1 = (pRnd[2] & 0x02) >> 1; // 22nd bit
84 | uint8_t sign2 = pRnd[2] & 0x01; // 23rd bit
85 |
86 | // Assuming that sign1 is either 0 or 1, flips sample1 iff sign1 = 1
87 | s[i] = ((-sign1) ^ sample1) + sign1;
88 |
89 | if (i + 1 < n) {
90 | s[i + 1] = ((-sign2) ^ sample2) + sign2;
91 | }
92 | }
93 |
94 | memset(rnd, 0, rndlen);
95 | free(rnd);
96 | return 1;
97 | }
98 |
99 |
100 | static int lwe_sample_n_inverse_16(uint16_t *s, const size_t n, const uint16_t *cdf_table, const size_t cdf_table_len, OQS_RAND *rand)
101 | { // Fills vector s with n samples from the noise distribution which requires 16 bits to sample. The distribution is specified by its CDF.
102 | // Super-constant timing: the CDF table is ingested for every sample.
103 | size_t rndlen = 2 * n;
104 | uint16_t *rndvec = (uint16_t *)malloc(rndlen);
105 |
106 | if (rndvec == NULL) {
107 | return 0;
108 | }
109 | OQS_RAND_n(rand, (uint8_t *) rndvec, rndlen);
110 |
111 | size_t i, j;
112 |
113 | for (i = 0; i < n; ++i) {
114 | uint8_t sample = 0;
115 | uint16_t rnd = rndvec[i] >> 1; // Drop the least significant bit
116 | uint8_t sign = rndvec[i] & 0x1; // Pick the least significant bit
117 |
118 | // No need to compare with the last value.
119 | for (j = 0; j < cdf_table_len - 1; j++) {
120 | // Constant time comparison: 1 if LWE_CDF_TABLE[j] < rnd, 0 otherwise.
121 | // Critically uses the fact that LWE_CDF_TABLE[j] and rnd fit in 15 bits.
122 | sample += (uint16_t)(cdf_table[j] - rnd) >> 15;
123 | }
124 | // Assuming that sign is either 0 or 1, flips sample iff sign = 1
125 | s[i] = ((-sign) ^ sample) + sign;
126 | }
127 |
128 | memset(rndvec, 0, rndlen);
129 | free(rndvec);
130 | return 1;
131 | }
132 |
133 |
134 | int oqs_kex_lwe_frodo_sample_n(uint16_t *s, const size_t n, struct oqs_kex_lwe_frodo_params *params, OQS_RAND *rand)
135 | {
136 | switch (params->sampler_num) {
137 | case 8: {
138 | // Have to copy cdf_table from uint16_t to uint8_t
139 | uint8_t *cdf_table_8 = malloc(params->cdf_table_len * sizeof(uint8_t));
140 | if (NULL == cdf_table_8) {
141 | return 0;
142 | }
143 | for (size_t i = 0; i < params->cdf_table_len; i++) {
144 | cdf_table_8[i] = (uint8_t) params->cdf_table[i];
145 | }
146 | int ret = lwe_sample_n_inverse_8(s, n, cdf_table_8, params->cdf_table_len, rand);
147 | free(cdf_table_8);
148 | return ret;
149 | }
150 | case 12:
151 | return lwe_sample_n_inverse_12(s, n, params->cdf_table, params->cdf_table_len, rand);
152 | case 16:
153 | return lwe_sample_n_inverse_16(s, n, params->cdf_table, params->cdf_table_len, rand);
154 | default:
155 | return 0;
156 | }
157 | }
158 |
--------------------------------------------------------------------------------
/src/random/rand.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #if defined(WINDOWS)
5 | #include
6 | #include
7 | #else
8 | #include
9 | #include
10 | #include
11 | #endif
12 |
13 | #include "rand.h"
14 | #include "rand_urandom_aesctr/rand_urandom_aesctr.h"
15 |
16 |
17 | OQS_RAND *OQS_RAND_new(enum OQS_RAND_alg_name alg_name) {
18 | switch (alg_name) {
19 | case OQS_RAND_alg_default:
20 | case OQS_RAND_alg_urandom_aesctr:
21 | return OQS_RAND_urandom_aesctr_new();
22 | default:
23 | assert(0);
24 | return NULL; // Avoid the warning of potentialy uninitialized variable in VS
25 | }
26 | }
27 |
28 | uint8_t OQS_RAND_8(OQS_RAND *r) {
29 | return r->rand_8(r);
30 | }
31 |
32 | uint32_t OQS_RAND_32(OQS_RAND *r) {
33 | return r->rand_32(r);
34 | }
35 |
36 | uint64_t OQS_RAND_64(OQS_RAND *r) {
37 | return r->rand_64(r);
38 | }
39 |
40 | void OQS_RAND_n(OQS_RAND *r, uint8_t *out, size_t n) {
41 | r->rand_n(r, out, n);
42 | }
43 |
44 | void OQS_RAND_free(OQS_RAND *r) {
45 | if (r) {
46 | r->free(r);
47 | }
48 | }
49 |
50 | __inline void OQS_RAND_test_record_occurrence(const unsigned char b, unsigned long occurrences[256]) {
51 | occurrences[b] += 1;
52 | }
53 |
54 |
55 | double OQS_RAND_test_statistical_distance_from_uniform(const unsigned long occurrences[256]) {
56 |
57 | // compute total number of samples
58 | unsigned long total = 0;
59 | for (int i = 0; i < 256; i++) {
60 | total += occurrences[i];
61 | }
62 |
63 | // compute statistical distance from uniform
64 | // SD(X,Y) = 1/2 \sum_z | Pr[X=z] - Pr[Y=z] |
65 | // = 1/2 \sum_z | 1/256 - Pr[Y=z] |
66 | double distance = 0.0;
67 | for (int i = 0; i < 256; i++) {
68 | distance += fabs(1.0 / 256.0 - (double) occurrences[i] / (double) total);
69 | }
70 | distance /= 2.0;
71 |
72 | return distance;
73 | }
74 |
75 |
76 | // Even for a perfectly uniform generator, if the number of samples is
77 | // low then the std dev of the counts will be high. So, instead, whilst
78 | // still assuming the number of samples isn't super-low, we calculate an
79 | // approximate Chi-squared statistic and back-convert to the Normal
80 | // distribution. The number of sigmas is reported: -3 to +3 is pretty
81 | // ordinary, big negative is suspiciously-flat counts, big positive is
82 | // wildly-fluctuating counts.
83 | double OQS_RAND_zscore_deviation_from_uniform(const unsigned long occurrences[256]) {
84 | double quantiles[102] = {
85 | 156.7872, 158.4155, 160.0555, 161.7072, 163.3707, 165.0460, 166.7331, 168.4321,
86 | 170.1430, 171.8658, 173.6006, 175.3475, 177.1064, 178.8773, 180.6604, 182.4557,
87 | 184.2631, 186.0828, 187.9147, 189.7589, 191.6155, 193.4844, 195.3657, 197.2594,
88 | 199.1656, 201.0843, 203.0155, 204.9593, 206.9157, 208.8847, 210.8663, 212.8607,
89 | 214.8678, 216.8877, 218.9203, 220.9658, 223.0241, 225.0953, 227.1794, 229.2765,
90 | 231.3866, 233.5096, 235.6457, 237.7949, 239.9572, 242.1326, 244.3212, 246.5230,
91 | 248.7380, 250.9663, 253.2079, 255.4627, 257.7310, 260.0126, 262.3076, 264.6160,
92 | 266.9379, 269.2733, 271.6222, 273.9846, 276.3607, 278.7503, 281.1536, 283.5705,
93 | 286.0011, 288.4454, 290.9035, 293.3754, 295.8610, 298.3605, 300.8739, 303.4011,
94 | 305.9422, 308.4973, 311.0663, 313.6493, 316.2463, 318.8574, 321.4825, 324.1217,
95 | 326.7751, 329.4426, 332.1242, 334.8201, 337.5301, 340.2544, 342.9930, 345.7459,
96 | 348.5131, 351.2947, 354.0906, 356.9009, 359.7256, 362.5648, 365.4184, 368.2866,
97 | 371.1692, 374.0664, 376.9782, 379.9045, 382.8454, 385.8010}; // -5.05 to +5.05 sigma: qchisq(pnorm(seq(-5.05,5.05,length.out=102)),255)
98 | unsigned long total;
99 | double chsq;
100 | int i;
101 |
102 | for (total = i = 0; i < 256; i++) {
103 | total += occurrences[i];
104 | }
105 | if (total / 256. < 5) {
106 | return ZSCORE_SPARSE;
107 | }
108 |
109 | for (chsq = i = 0; i < 256; i++) {
110 | chsq += pow(occurrences[i] - total / 256., 2) * 256. / total;
111 | }
112 |
113 | if (chsq <= quantiles[0]) {
114 | return ZSCORE_BIGNEG;
115 | }
116 | for (i = 1; i < 102; i++) {
117 | if (chsq <= quantiles[i]) {
118 | return (i - 51) / 10.0;
119 | }
120 | }
121 | return ZSCORE_BIGPOS;
122 | }
123 |
124 |
125 | // Convenience function for statistics reporting
126 | void OQS_RAND_report_statistics(const unsigned long occurrences[256], const char *indent) {
127 | double zscore = OQS_RAND_zscore_deviation_from_uniform(occurrences);
128 | printf("%sStatistical distance from uniform: %12.10f\n", indent, OQS_RAND_test_statistical_distance_from_uniform(occurrences));
129 | printf("%s Z-score deviation from uniform: ", indent);
130 | if (zscore == ZSCORE_BIGNEG) {
131 | printf("less than -5.0 sigma ***\n");
132 | } else if (zscore == ZSCORE_BIGPOS) {
133 | printf("more than +5.0 sigma ***\n");
134 | } else if (zscore == ZSCORE_SPARSE) {
135 | printf("(too few data)\n");
136 | } else {
137 | printf("about %.1f sigma\n", zscore);
138 | }
139 | return;
140 | }
141 |
142 | int OQS_RAND_get_system_entropy(uint8_t *buf, size_t n) {
143 | int result = 0;
144 |
145 | #if !defined(WINDOWS)
146 | int fd = 0;
147 | #endif
148 |
149 | if (!buf) {
150 | goto err;
151 | }
152 |
153 | #if defined(WINDOWS)
154 | HCRYPTPROV hCryptProv;
155 | if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) ||
156 | !CryptGenRandom(hCryptProv, n, buf)) {
157 | goto err;
158 | }
159 | #else
160 | fd = open("/dev/urandom", O_RDONLY);
161 | if (fd <= 0) {
162 | goto err;
163 | }
164 | size_t r = read(fd, buf, n);
165 | if (r != n) {
166 | goto err;
167 | }
168 | #endif
169 | result = 1;
170 |
171 | err:
172 | #if !defined(WINDOWS)
173 | if (fd > 0) {
174 | close(fd);
175 | }
176 | #endif
177 |
178 | return result;
179 | }
180 |
--------------------------------------------------------------------------------
/src/random/rand.h:
--------------------------------------------------------------------------------
1 | /**
2 | * \file rand.h
3 | * \brief Header defining the generic OQS PRNG
4 | */
5 |
6 | #ifndef __OQS_RAND_H
7 | #define __OQS_RAND_H
8 |
9 | #include
10 | #include
11 |
12 | enum OQS_RAND_alg_name {
13 | OQS_RAND_alg_default,
14 | OQS_RAND_alg_urandom_chacha20,
15 | OQS_RAND_alg_urandom_aesctr,
16 | };
17 |
18 | typedef struct OQS_RAND OQS_RAND;
19 |
20 | /**
21 | * OQS PRNG object
22 | */
23 | typedef struct OQS_RAND {
24 |
25 | /**
26 | * Specifies the name of the random number function
27 | */
28 | char *method_name;
29 |
30 | /**
31 | * Estimated number of bits of security provided against a classical
32 | * attacker
33 | */
34 | uint16_t estimated_classical_security;
35 |
36 | /**
37 | * Estimated number of bits of security provided against a quantum
38 | * attacker
39 | */
40 | uint16_t estimated_quantum_security;
41 |
42 | /**
43 | * Pointer for storing the state of the PRNG
44 | */
45 | void *ctx;
46 |
47 | /**
48 | * Function which returns an 8-bit random unsigned integer
49 | */
50 | uint8_t (*rand_8)(OQS_RAND *r);
51 |
52 | /**
53 | * Function which returns an 32-bit random unsigned integer
54 | */
55 | uint32_t (*rand_32)(OQS_RAND *r);
56 |
57 | /**
58 | * Function which returns an 64-bit random unsigned integer
59 | */
60 | uint64_t (*rand_64)(OQS_RAND *r);
61 |
62 | /**
63 | * Function which generates n random 8-bit unsigned integers
64 | *
65 | * @param out : pointer to an array large enough to store the output integers (\f$\text{size} \geq n\f$)
66 | * @param n : number of integers to generate
67 | */
68 | void (*rand_n)(OQS_RAND *r, uint8_t *out, size_t n);
69 |
70 | /**
71 | * Pointer to a function for freeing the allocated key exchange structure
72 | *
73 | * @param k : Key exchange structure
74 | *
75 | */
76 | void (*free)(OQS_RAND *r);
77 |
78 | } OQS_RAND;
79 |
80 | OQS_RAND *OQS_RAND_new(enum OQS_RAND_alg_name alg_name);
81 |
82 | uint8_t OQS_RAND_8(OQS_RAND *r);
83 | uint32_t OQS_RAND_32(OQS_RAND *r);
84 | uint64_t OQS_RAND_64(OQS_RAND *r);
85 | void OQS_RAND_n(OQS_RAND *r, uint8_t *out, size_t n);
86 |
87 | void OQS_RAND_free(OQS_RAND *r);
88 |
89 | extern void OQS_RAND_test_record_occurrence(const unsigned char b, unsigned long occurrences[256]);
90 | double OQS_RAND_test_statistical_distance_from_uniform(const unsigned long occurrences[256]);
91 |
92 | #define ZSCORE_SPARSE (999.999)
93 | #define ZSCORE_BIGNEG (-100.0)
94 | #define ZSCORE_BIGPOS (+100.0)
95 | double OQS_RAND_zscore_deviation_from_uniform(const unsigned long occurrences[256]);
96 | void OQS_RAND_report_statistics(const unsigned long occurrences[256], const char *indent);
97 |
98 | int OQS_RAND_get_system_entropy(uint8_t *buf, size_t n);
99 | #endif
100 |
--------------------------------------------------------------------------------
/src/random/rand_urandom_aesctr/rand_urandom_aesctr.c:
--------------------------------------------------------------------------------
1 | #include
2 | #if defined(WINDOWS)
3 | #include
4 | #include
5 | #else
6 | #include
7 | #include
8 | #include
9 | #endif
10 | #include
11 | #include
12 | #include
13 | #include //memcpy
14 |
15 | #include
16 | #include "../rand.h"
17 | #include "rand_urandom_aesctr.h"
18 | #include "../../aes/aes.h"
19 |
20 | typedef struct oqs_rand_urandom_aesctr_ctx {
21 | uint64_t ctr;
22 | void *schedule;
23 | uint8_t cache[64];
24 | size_t cache_next_byte;
25 | } oqs_rand_urandom_aesctr_ctx;
26 |
27 | static oqs_rand_urandom_aesctr_ctx *oqs_rand_urandom_aesctr_ctx_new() {
28 | oqs_rand_urandom_aesctr_ctx *rand_ctx = NULL;
29 | rand_ctx = (oqs_rand_urandom_aesctr_ctx *) malloc(sizeof(oqs_rand_urandom_aesctr_ctx));
30 | if (rand_ctx == NULL) {
31 | goto err;
32 | }
33 | uint8_t key[16];
34 | if (!OQS_RAND_get_system_entropy(key, 16)) {
35 | goto err;
36 | }
37 | OQS_AES128_load_schedule(key, &rand_ctx->schedule, 1);
38 | rand_ctx->cache_next_byte = 64; // cache is empty
39 | rand_ctx->ctr = 0;
40 | goto okay;
41 | err:
42 | if (rand_ctx) {
43 | free(rand_ctx);
44 | }
45 | return NULL;
46 | okay:
47 | return rand_ctx;
48 | }
49 |
50 | void OQS_RAND_urandom_aesctr_n(OQS_RAND *r, uint8_t *out, size_t n) {
51 | oqs_rand_urandom_aesctr_ctx *rand_ctx = (oqs_rand_urandom_aesctr_ctx *) r->ctx;
52 | const uint64_t num_full_blocks = n / 16;
53 | uint64_t *half_blocks = (uint64_t *) out;
54 | for (size_t i = 0; i < num_full_blocks; i++) {
55 | half_blocks[2 * i] = rand_ctx->ctr++;
56 | half_blocks[2 * i + 1] = rand_ctx->ctr++;
57 | }
58 | OQS_AES128_ECB_enc_sch(out, 16 * num_full_blocks, rand_ctx->schedule, out);
59 | if (n % 16 > 0) {
60 | uint8_t tmp_8[16];
61 | uint64_t *tmp_64 = (uint64_t *) tmp_8;
62 | tmp_64[0] = rand_ctx->ctr++;
63 | tmp_64[1] = rand_ctx->ctr++;
64 | OQS_AES128_ECB_enc_sch(tmp_8, 16, rand_ctx->schedule, tmp_8);
65 | memcpy(out + 16 * num_full_blocks, tmp_8, n % 16);
66 | }
67 | }
68 |
69 | static void OQS_RAND_urandom_aesctr_fill_cache(OQS_RAND *r) {
70 | oqs_rand_urandom_aesctr_ctx *rand_ctx = (oqs_rand_urandom_aesctr_ctx *) r->ctx;
71 | OQS_RAND_urandom_aesctr_n(r, rand_ctx->cache, sizeof(rand_ctx->cache));
72 | rand_ctx->cache_next_byte = 0;
73 | }
74 |
75 | uint8_t OQS_RAND_urandom_aesctr_8(OQS_RAND *r) {
76 | oqs_rand_urandom_aesctr_ctx *rand_ctx = (oqs_rand_urandom_aesctr_ctx *) r->ctx;
77 | if (rand_ctx->cache_next_byte > sizeof(rand_ctx->cache) - 1) {
78 | OQS_RAND_urandom_aesctr_fill_cache(r);
79 | }
80 | uint8_t out = rand_ctx->cache[rand_ctx->cache_next_byte];
81 | rand_ctx->cache_next_byte += 1;
82 | return out;
83 | }
84 |
85 | uint32_t OQS_RAND_urandom_aesctr_32(OQS_RAND *r) {
86 | oqs_rand_urandom_aesctr_ctx *rand_ctx = (oqs_rand_urandom_aesctr_ctx *) r->ctx;
87 | if (rand_ctx->cache_next_byte > sizeof(rand_ctx->cache) - 4) {
88 | OQS_RAND_urandom_aesctr_fill_cache(r);
89 | }
90 | uint32_t out;
91 | memcpy(&out, &rand_ctx->cache[rand_ctx->cache_next_byte], 4);
92 | rand_ctx->cache_next_byte += 4;
93 | return out;
94 | }
95 |
96 | uint64_t OQS_RAND_urandom_aesctr_64(OQS_RAND *r) {
97 | oqs_rand_urandom_aesctr_ctx *rand_ctx = (oqs_rand_urandom_aesctr_ctx *) r->ctx;
98 | if (rand_ctx->cache_next_byte > sizeof(rand_ctx->cache) - 8) {
99 | OQS_RAND_urandom_aesctr_fill_cache(r);
100 | }
101 | uint64_t out;
102 | memcpy(&out, &rand_ctx->cache[rand_ctx->cache_next_byte], 8);
103 | rand_ctx->cache_next_byte += 8;
104 | return out;
105 | }
106 |
107 | void OQS_RAND_urandom_aesctr_free(OQS_RAND *r) {
108 | if (r) {
109 | oqs_rand_urandom_aesctr_ctx *rand_ctx = (oqs_rand_urandom_aesctr_ctx *) r->ctx;
110 | if (rand_ctx) {
111 | OQS_AES128_free_schedule(rand_ctx->schedule);
112 | }
113 | free(r->ctx);
114 | free(r->method_name);
115 | }
116 | free(r);
117 | }
118 |
119 | OQS_RAND *OQS_RAND_urandom_aesctr_new() {
120 | OQS_RAND *r = malloc(sizeof(OQS_RAND));
121 | if (r == NULL) {
122 | return NULL;
123 | }
124 | r->method_name = strdup("urandom_aesctr");
125 | r->ctx = oqs_rand_urandom_aesctr_ctx_new();
126 | if (r->ctx == NULL || r->method_name == NULL) {
127 | OQS_RAND_urandom_aesctr_free(r);
128 | return NULL;
129 | }
130 | r->estimated_classical_security = 128;
131 | r->estimated_quantum_security = 64; // Grover search
132 | r->rand_8 = &OQS_RAND_urandom_aesctr_8;
133 | r->rand_32 = &OQS_RAND_urandom_aesctr_32;
134 | r->rand_64 = &OQS_RAND_urandom_aesctr_64;
135 | r->rand_n = &OQS_RAND_urandom_aesctr_n;
136 | r->free = &OQS_RAND_urandom_aesctr_free;
137 | return r;
138 | }
139 |
--------------------------------------------------------------------------------
/src/random/rand_urandom_aesctr/rand_urandom_aesctr.h:
--------------------------------------------------------------------------------
1 | /**
2 | * \file rand_urandom_aesctr.h
3 | * \brief Header for the chacha implementation of OQS_RAND
4 | */
5 |
6 | #ifndef __OQS_RAND_URANDOM_AESCTR_H
7 | #define __OQS_RAND_URANDOM_AESCTR_H
8 |
9 | #include
10 | #include
11 |
12 | #include "../rand.h"
13 |
14 | OQS_RAND *OQS_RAND_urandom_aesctr_new();
15 |
16 | uint8_t OQS_RAND_urandom_aesctr_8(OQS_RAND *r);
17 | uint32_t OQS_RAND_urandom_aesctr_32(OQS_RAND *r);
18 | uint64_t OQS_RAND_urandom_aesctr_64(OQS_RAND *r);
19 | void OQS_RAND_urandom_aesctr_n(OQS_RAND *r, uint8_t *out, size_t n);
20 |
21 | void OQS_RAND_urandom_aesctr_free(OQS_RAND *r);
22 |
23 | #endif
24 |
--------------------------------------------------------------------------------
/src/random/test_rand.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #include "rand.h"
9 |
10 | struct rand_testcase {
11 | enum OQS_RAND_alg_name alg_name;
12 | };
13 |
14 | /* Add new testcases here */
15 | struct rand_testcase rand_testcases[] = {
16 | {OQS_RAND_alg_urandom_aesctr},
17 | };
18 |
19 | #define RAND_TEST_ITERATIONS 10000000L
20 |
21 | static void rand_test_distribution_8(OQS_RAND *rand, unsigned long occurrences[256], int iterations) {
22 | uint8_t b;
23 | for (int i = 0; i < iterations; i++) {
24 | b = OQS_RAND_8(rand);
25 | OQS_RAND_test_record_occurrence(b, occurrences);
26 | }
27 | }
28 |
29 | static void rand_test_distribution_32(OQS_RAND *rand, unsigned long occurrences[256], int iterations) {
30 | uint32_t x;
31 | for (int i = 0; i < iterations; i++) {
32 | x = OQS_RAND_32(rand);
33 | uint8_t b;
34 | for (size_t j = 0; j < sizeof(uint32_t); j++) {
35 | b = (x >> j) & 0xFF;
36 | OQS_RAND_test_record_occurrence(b, occurrences);
37 | }
38 | }
39 | }
40 |
41 | static void rand_test_distribution_64(OQS_RAND *rand, unsigned long occurrences[256], int iterations) {
42 | uint64_t x;
43 | for (int i = 0; i < iterations; i++) {
44 | x = OQS_RAND_64(rand);
45 | uint8_t b;
46 | for (size_t j = 0; j < sizeof(uint64_t); j++) {
47 | b = (x >> j) & 0xFF;
48 | OQS_RAND_test_record_occurrence(b, occurrences);
49 | }
50 | }
51 | }
52 |
53 | static int rand_test_distribution_n(OQS_RAND *rand, unsigned long occurrences[256], int len) {
54 | uint8_t *x = malloc(len);
55 | if (x == NULL) {
56 | return 0;
57 | }
58 | OQS_RAND_n(rand, x, len);
59 | for (int i = 0; i < len; i++) {
60 | OQS_RAND_test_record_occurrence(x[i], occurrences);
61 | }
62 | free(x);
63 | return 1;
64 | }
65 |
66 | #define PRINT_HEX_STRING(label, str, len) \
67 | { \
68 | printf("%-20s (%4zu bytes): ", (label), (size_t)(len)); \
69 | for (size_t i = 0; i < (len); i++) { \
70 | printf("%02X", ((unsigned char *) (str))[i]); \
71 | } \
72 | printf("\n"); \
73 | }
74 |
75 | static int rand_test_distribution_wrapper(enum OQS_RAND_alg_name alg_name, int iterations, bool quiet) {
76 |
77 | OQS_RAND *rand = OQS_RAND_new(alg_name);
78 | if (rand == NULL) {
79 | fprintf(stderr, "rand is NULL\n");
80 | return 0;
81 | }
82 |
83 | if (!quiet) {
84 | printf("================================================================================\n");
85 | printf("Sample outputs of PRNG %s\n", rand->method_name);
86 | printf("================================================================================\n");
87 |
88 | uint8_t x[256];
89 | OQS_RAND_n(rand, x, 256);
90 | PRINT_HEX_STRING("OQS_RAND_n, n = 256", x, 256)
91 |
92 | uint8_t y8 = OQS_RAND_8(rand);
93 | PRINT_HEX_STRING("OQS_RAND_8", (uint8_t *) &y8, sizeof(y8));
94 | y8 = OQS_RAND_8(rand);
95 | PRINT_HEX_STRING("OQS_RAND_8", (uint8_t *) &y8, sizeof(y8));
96 |
97 | uint32_t y32 = OQS_RAND_32(rand);
98 | PRINT_HEX_STRING("OQS_RAND_32", (uint8_t *) &y32, sizeof(y32));
99 | y32 = OQS_RAND_32(rand);
100 | PRINT_HEX_STRING("OQS_RAND_32", (uint8_t *) &y32, sizeof(y32));
101 |
102 | uint64_t y64 = OQS_RAND_64(rand);
103 | PRINT_HEX_STRING("OQS_RAND_64", (uint8_t *) &y64, sizeof(y64));
104 | y64 = OQS_RAND_64(rand);
105 | PRINT_HEX_STRING("OQS_RAND_64", (uint8_t *) &y64, sizeof(y64));
106 |
107 | OQS_RAND_n(rand, x, 256);
108 | PRINT_HEX_STRING("OQS_RAND_n, n = 256", x, 256)
109 | }
110 |
111 | printf("================================================================================\n");
112 | printf("Testing distribution of PRNG %s\n", rand->method_name);
113 | printf("================================================================================\n");
114 |
115 | unsigned long occurrences[256];
116 | for (int i = 0; i < 256; i++) {
117 | occurrences[i] = 0;
118 | }
119 |
120 | printf("1-byte mode for %d iterations\n", 8 * iterations);
121 | rand_test_distribution_8(rand, occurrences, 8 * iterations);
122 | OQS_RAND_report_statistics(occurrences, " ");
123 |
124 | for (int i = 0; i < 256; i++) {
125 | occurrences[i] = 0;
126 | }
127 |
128 | printf("4-byte mode for %d iterations\n", 2 * iterations);
129 | rand_test_distribution_32(rand, occurrences, 2 * iterations);
130 | OQS_RAND_report_statistics(occurrences, " ");
131 |
132 | for (int i = 0; i < 256; i++) {
133 | occurrences[i] = 0;
134 | }
135 |
136 | printf("8-byte mode for %d iterations\n", iterations);
137 | rand_test_distribution_64(rand, occurrences, iterations);
138 | OQS_RAND_report_statistics(occurrences, " ");
139 |
140 | for (int i = 0; i < 256; i++) {
141 | occurrences[i] = 0;
142 | }
143 |
144 | printf("n-byte mode for %d bytes\n", 8 * iterations);
145 | rand_test_distribution_n(rand, occurrences, 8 * iterations);
146 | OQS_RAND_report_statistics(occurrences, " ");
147 |
148 | OQS_RAND_free(rand);
149 |
150 | return 1;
151 | }
152 |
153 | int main(int argc, char **argv) {
154 |
155 | int success;
156 | bool quiet = false;
157 |
158 | for (int i = 1; i < argc; i++) {
159 | if (argv[i][0] == '-') {
160 | if (strcmp(argv[i], "--quiet") == 0 || strcmp(argv[i], "-q") == 0) {
161 | quiet = true;
162 | } else {
163 | printf("Usage: ./test_rand [options]\n");
164 | printf("\nOptions:\n");
165 | printf(" --quiet, -q\n");
166 | printf(" Less verbose output\n");
167 | if ((strcmp(argv[i], "-h") == 0) || (strcmp(argv[i], "-help") == 0) || (strcmp(argv[i], "--help") == 0)) {
168 | return EXIT_SUCCESS;
169 | } else {
170 | return EXIT_FAILURE;
171 | }
172 | }
173 | }
174 | }
175 |
176 | size_t rand_testcases_len = sizeof(rand_testcases) / sizeof(struct rand_testcase);
177 | for (size_t i = 0; i < rand_testcases_len; i++) {
178 | success = rand_test_distribution_wrapper(rand_testcases[i].alg_name, RAND_TEST_ITERATIONS, quiet);
179 | if (success != 1) {
180 | goto err;
181 | }
182 | }
183 |
184 | success = 1;
185 | goto cleanup;
186 |
187 | err:
188 | success = 0;
189 | fprintf(stderr, "ERROR!\n");
190 |
191 | cleanup:
192 |
193 | return (success == 1) ? EXIT_SUCCESS : EXIT_FAILURE;
194 | }
195 |
--------------------------------------------------------------------------------
/src/sha3/fips202.h:
--------------------------------------------------------------------------------
1 | #ifndef FIPS202_H
2 | #define FIPS202_H
3 |
4 | #include
5 |
6 |
7 | #define SHAKE128_RATE 168
8 | #define SHAKE256_RATE 136
9 |
10 | void shake128_absorb(uint64_t *s, const unsigned char *input, unsigned int inputByteLen);
11 | void shake128_squeezeblocks(unsigned char *output, unsigned long long nblocks, uint64_t *s);
12 | void shake128(unsigned char *output, unsigned long long outlen, const unsigned char *input, unsigned long long inlen);
13 |
14 | void cshake128_simple_absorb(uint64_t *s, uint16_t cstm, const unsigned char *in, unsigned long long inlen);
15 | void cshake128_simple_squeezeblocks(unsigned char *output, unsigned long long nblocks, uint64_t *s);
16 | void cshake128_simple(unsigned char *output, unsigned long long outlen, uint16_t cstm, const unsigned char *in, unsigned long long inlen);
17 |
18 | void shake256_absorb(uint64_t *s, const unsigned char *input, unsigned int inputByteLen);
19 | void shake256_squeezeblocks(unsigned char *output, unsigned long long nblocks, uint64_t *s);
20 | void shake256(unsigned char *output, unsigned long long outlen, const unsigned char *input, unsigned long long inlen);
21 |
22 | void cshake256_simple_absorb(uint64_t *s, uint16_t cstm, const unsigned char *in, unsigned long long inlen);
23 | void cshake256_simple_squeezeblocks(unsigned char *output, unsigned long long nblocks, uint64_t *s);
24 | void cshake256_simple(unsigned char *output, unsigned long long outlen, uint16_t cstm, const unsigned char *in, unsigned long long inlen);
25 |
26 | void kmac256_simple(unsigned char *output, uint8_t outlen, uint16_t cstm, const unsigned char *in, unsigned long long inlen, const unsigned char *key, uint8_t keylen, unsigned char *temp);
27 |
28 |
29 | #endif
30 |
--------------------------------------------------------------------------------
/src/sha3/fips202x4.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include "fips202.h"
5 |
6 | #define NROUNDS 24
7 | #define ROL(a, offset) ((a << offset) ^ (a >> (64-offset)))
8 |
9 | static uint64_t load64(const unsigned char *x)
10 | {
11 | unsigned long long r = 0, i;
12 |
13 | for (i = 0; i < 8; ++i) {
14 | r |= (unsigned long long)x[i] << 8 * i;
15 | }
16 | return r;
17 | }
18 |
19 | static void store64(uint8_t *x, uint64_t u)
20 | {
21 | unsigned int i;
22 |
23 | for(i=0; i<8; ++i) {
24 | x[i] = u;
25 | u >>= 8;
26 | }
27 | }
28 |
29 | /* Use implementation from the Keccak Code Package */
30 | extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s);
31 | #define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds
32 |
33 |
34 | static void keccak_absorb4x(__m256i *s,
35 | unsigned int r,
36 | const unsigned char *m0,
37 | const unsigned char *m1,
38 | const unsigned char *m2,
39 | const unsigned char *m3,
40 | unsigned long long int mlen,
41 | unsigned char p)
42 | {
43 | unsigned long long i;
44 | unsigned char t0[200];
45 | unsigned char t1[200];
46 | unsigned char t2[200];
47 | unsigned char t3[200];
48 |
49 | unsigned long long *ss = (unsigned long long *)s;
50 |
51 |
52 | while (mlen >= r)
53 | {
54 | for (i = 0; i < r / 8; ++i)
55 | {
56 | ss[4*i+0] ^= load64(m0 + 8 * i);
57 | ss[4*i+1] ^= load64(m1 + 8 * i);
58 | ss[4*i+2] ^= load64(m2 + 8 * i);
59 | ss[4*i+3] ^= load64(m3 + 8 * i);
60 | }
61 |
62 | KeccakF1600_StatePermute4x(s);
63 | mlen -= r;
64 | m0 += r;
65 | m1 += r;
66 | m2 += r;
67 | m3 += r;
68 | }
69 |
70 | for (i = 0; i < r; ++i)
71 | {
72 | t0[i] = 0;
73 | t1[i] = 0;
74 | t2[i] = 0;
75 | t3[i] = 0;
76 | }
77 | for (i = 0; i < mlen; ++i)
78 | {
79 | t0[i] = m0[i];
80 | t1[i] = m1[i];
81 | t2[i] = m2[i];
82 | t3[i] = m3[i];
83 | }
84 |
85 | t0[i] = p;
86 | t1[i] = p;
87 | t2[i] = p;
88 | t3[i] = p;
89 |
90 | t0[r - 1] |= 128;
91 | t1[r - 1] |= 128;
92 | t2[r - 1] |= 128;
93 | t3[r - 1] |= 128;
94 |
95 | for (i = 0; i < r / 8; ++i)
96 | {
97 | ss[4*i+0] ^= load64(t0 + 8 * i);
98 | ss[4*i+1] ^= load64(t1 + 8 * i);
99 | ss[4*i+2] ^= load64(t2 + 8 * i);
100 | ss[4*i+3] ^= load64(t3 + 8 * i);
101 | }
102 | }
103 |
104 |
105 | static void keccak_squeezeblocks4x(unsigned char *h0,
106 | unsigned char *h1,
107 | unsigned char *h2,
108 | unsigned char *h3,
109 | unsigned long long int nblocks,
110 | __m256i *s,
111 | unsigned int r)
112 | {
113 | unsigned int i;
114 |
115 | unsigned long long *ss = (unsigned long long *)s;
116 |
117 | while(nblocks > 0)
118 | {
119 | KeccakF1600_StatePermute4x(s);
120 | for(i=0;i<(r>>3);i++)
121 | {
122 | store64(h0+8*i, ss[4*i+0]);
123 | store64(h1+8*i, ss[4*i+1]);
124 | store64(h2+8*i, ss[4*i+2]);
125 | store64(h3+8*i, ss[4*i+3]);
126 | }
127 | h0 += r;
128 | h1 += r;
129 | h2 += r;
130 | h3 += r;
131 | nblocks--;
132 | }
133 | }
134 |
135 | void cshake128_simple_absorb4x(__m256i *s,
136 | uint16_t cstm0,
137 | uint16_t cstm1,
138 | uint16_t cstm2,
139 | uint16_t cstm3,
140 | const unsigned char *in, unsigned long long inlen)
141 | {
142 | unsigned char *sep = (unsigned char *)s;
143 | unsigned int i;
144 |
145 | for(i=0;i<25;i++)
146 | s[i] = _mm256_xor_si256(s[i], s[i]); // zero state
147 |
148 | /* Absorb customization (domain-separation) string */
149 | for(i=0;i<4;i++)
150 | {
151 | sep[8*i+0] = 0x01;
152 | sep[8*i+1] = 0xa8;
153 | sep[8*i+2] = 0x01;
154 | sep[8*i+3] = 0x00;
155 | sep[8*i+4] = 0x01;
156 | sep[8*i+5] = 16;
157 | }
158 | sep[ 6] = cstm0 & 0xff;
159 | sep[ 7] = cstm0 >> 8;
160 | sep[14] = cstm1 & 0xff;
161 | sep[15] = cstm1 >> 8;
162 | sep[22] = cstm2 & 0xff;
163 | sep[23] = cstm2 >> 8;
164 | sep[30] = cstm3 & 0xff;
165 | sep[31] = cstm3 >> 8;
166 |
167 | KeccakF1600_StatePermute4x(s);
168 |
169 | /* Absorb input */
170 | keccak_absorb4x(s, SHAKE128_RATE, in, in, in, in, inlen, 0x04);
171 | }
172 |
173 | void cshake128_simple_squeezeblocks4x(unsigned char *output0,
174 | unsigned char *output1,
175 | unsigned char *output2,
176 | unsigned char *output3, unsigned long long outlen,
177 | __m256i *s)
178 | {
179 | keccak_squeezeblocks4x(output0, output1, output2, output3, outlen/SHAKE128_RATE, s, SHAKE128_RATE);
180 | }
181 |
182 |
183 | /* N is assumed to be empty; S is assumed to have at most 2 characters */
184 | void cshake128_simple4x(unsigned char *output0,
185 | unsigned char *output1,
186 | unsigned char *output2,
187 | unsigned char *output3, unsigned long long outlen,
188 | uint16_t cstm0,
189 | uint16_t cstm1,
190 | uint16_t cstm2,
191 | uint16_t cstm3,
192 | const unsigned char *in, unsigned long long inlen)
193 | {
194 | __m256i s[25];
195 | unsigned char t0[SHAKE128_RATE];
196 | unsigned char t1[SHAKE128_RATE];
197 | unsigned char t2[SHAKE128_RATE];
198 | unsigned char t3[SHAKE128_RATE];
199 | unsigned int i;
200 |
201 | cshake128_simple_absorb4x(s,cstm0,cstm1,cstm2,cstm3,in,inlen);
202 |
203 | /* Squeeze output */
204 | keccak_squeezeblocks4x(output0, output1, output2, output3, outlen/SHAKE128_RATE, s, SHAKE128_RATE);
205 | output0 += (outlen/SHAKE128_RATE)*SHAKE128_RATE;
206 | output1 += (outlen/SHAKE128_RATE)*SHAKE128_RATE;
207 | output2 += (outlen/SHAKE128_RATE)*SHAKE128_RATE;
208 | output3 += (outlen/SHAKE128_RATE)*SHAKE128_RATE;
209 |
210 | if(outlen%SHAKE128_RATE)
211 | {
212 | keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE);
213 | for(i=0;i
5 |
6 | void cshake128_simple_absorb4x(__m256i *s,
7 | uint16_t cstm0,
8 | uint16_t cstm1,
9 | uint16_t cstm2,
10 | uint16_t cstm3,
11 | const unsigned char *in, unsigned long long inlen);
12 |
13 | void cshake128_simple_squeezeblocks4x(unsigned char *output0,
14 | unsigned char *output1,
15 | unsigned char *output2,
16 | unsigned char *output3, unsigned long long outlen,
17 | __m256i *s);
18 |
19 |
20 | /* N is assumed to be empty; S is assumed to have at most 2 characters */
21 | void cshake128_simple4x(unsigned char *output0,
22 | unsigned char *output1,
23 | unsigned char *output2,
24 | unsigned char *output3, unsigned long long outlen,
25 | uint16_t cstm0,
26 | uint16_t cstm1,
27 | uint16_t cstm2,
28 | uint16_t cstm3,
29 | const unsigned char *in, unsigned long long inlen);
30 |
31 | #endif
32 |
--------------------------------------------------------------------------------
/src/sha3/keccak4x/KeccakP-1600-times4-SnP.h:
--------------------------------------------------------------------------------
1 | /*
2 | Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni,
3 | Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby
4 | denoted as "the implementer".
5 |
6 | For more information, feedback or questions, please refer to our websites:
7 | http://keccak.noekeon.org/
8 | http://keyak.noekeon.org/
9 | http://ketje.noekeon.org/
10 |
11 | To the extent possible under law, the implementer has waived all copyright
12 | and related or neighboring rights to the source code in this file.
13 | http://creativecommons.org/publicdomain/zero/1.0/
14 | */
15 |
16 | #ifndef _KeccakP_1600_times4_SnP_h_
17 | #define _KeccakP_1600_times4_SnP_h_
18 |
19 | /** For the documentation, see PlSnP-documentation.h.
20 | */
21 |
22 | #include "SIMD256-config.h"
23 |
24 | #define KeccakP1600times4_implementation "256-bit SIMD implementation (" KeccakP1600times4_implementation_config ")"
25 | #define KeccakP1600times4_statesSizeInBytes 800
26 | #define KeccakP1600times4_statesAlignment 32
27 | #define KeccakF1600times4_FastLoop_supported
28 | #define KeccakP1600times4_12rounds_FastLoop_supported
29 |
30 | #include
31 |
32 | #define KeccakP1600times4_StaticInitialize()
33 | void KeccakP1600times4_InitializeAll(void *states);
34 | #define KeccakP1600times4_AddByte(states, instanceIndex, byte, offset) \
35 | ((unsigned char*)(states))[(instanceIndex)*8 + ((offset)/8)*4*8 + (offset)%8] ^= (byte)
36 | void KeccakP1600times4_AddBytes(void *states, unsigned int instanceIndex, const unsigned char *data, unsigned int offset, unsigned int length);
37 | void KeccakP1600times4_AddLanesAll(void *states, const unsigned char *data, unsigned int laneCount, unsigned int laneOffset);
38 | void KeccakP1600times4_OverwriteBytes(void *states, unsigned int instanceIndex, const unsigned char *data, unsigned int offset, unsigned int length);
39 | void KeccakP1600times4_OverwriteLanesAll(void *states, const unsigned char *data, unsigned int laneCount, unsigned int laneOffset);
40 | void KeccakP1600times4_OverwriteWithZeroes(void *states, unsigned int instanceIndex, unsigned int byteCount);
41 | void KeccakP1600times4_PermuteAll_12rounds(void *states);
42 | void KeccakP1600times4_PermuteAll_24rounds(void *states);
43 | void KeccakP1600times4_ExtractBytes(const void *states, unsigned int instanceIndex, unsigned char *data, unsigned int offset, unsigned int length);
44 | void KeccakP1600times4_ExtractLanesAll(const void *states, unsigned char *data, unsigned int laneCount, unsigned int laneOffset);
45 | void KeccakP1600times4_ExtractAndAddBytes(const void *states, unsigned int instanceIndex, const unsigned char *input, unsigned char *output, unsigned int offset, unsigned int length);
46 | void KeccakP1600times4_ExtractAndAddLanesAll(const void *states, const unsigned char *input, unsigned char *output, unsigned int laneCount, unsigned int laneOffset);
47 | size_t KeccakF1600times4_FastLoop_Absorb(void *states, unsigned int laneCount, unsigned int laneOffsetParallel, unsigned int laneOffsetSerial, const unsigned char *data, size_t dataByteLen);
48 | size_t KeccakP1600times4_12rounds_FastLoop_Absorb(void *states, unsigned int laneCount, unsigned int laneOffsetParallel, unsigned int laneOffsetSerial, const unsigned char *data, size_t dataByteLen);
49 |
50 | #endif
51 |
--------------------------------------------------------------------------------
/src/sha3/keccak4x/KeccakP-1600-unrolling.macros:
--------------------------------------------------------------------------------
1 | /*
2 | Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni,
3 | Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby
4 | denoted as "the implementer".
5 |
6 | For more information, feedback or questions, please refer to our websites:
7 | http://keccak.noekeon.org/
8 | http://keyak.noekeon.org/
9 | http://ketje.noekeon.org/
10 |
11 | To the extent possible under law, the implementer has waived all copyright
12 | and related or neighboring rights to the source code in this file.
13 | http://creativecommons.org/publicdomain/zero/1.0/
14 | */
15 |
16 | #if (defined(FullUnrolling))
17 | #define rounds24 \
18 | prepareTheta \
19 | thetaRhoPiChiIotaPrepareTheta( 0, A, E) \
20 | thetaRhoPiChiIotaPrepareTheta( 1, E, A) \
21 | thetaRhoPiChiIotaPrepareTheta( 2, A, E) \
22 | thetaRhoPiChiIotaPrepareTheta( 3, E, A) \
23 | thetaRhoPiChiIotaPrepareTheta( 4, A, E) \
24 | thetaRhoPiChiIotaPrepareTheta( 5, E, A) \
25 | thetaRhoPiChiIotaPrepareTheta( 6, A, E) \
26 | thetaRhoPiChiIotaPrepareTheta( 7, E, A) \
27 | thetaRhoPiChiIotaPrepareTheta( 8, A, E) \
28 | thetaRhoPiChiIotaPrepareTheta( 9, E, A) \
29 | thetaRhoPiChiIotaPrepareTheta(10, A, E) \
30 | thetaRhoPiChiIotaPrepareTheta(11, E, A) \
31 | thetaRhoPiChiIotaPrepareTheta(12, A, E) \
32 | thetaRhoPiChiIotaPrepareTheta(13, E, A) \
33 | thetaRhoPiChiIotaPrepareTheta(14, A, E) \
34 | thetaRhoPiChiIotaPrepareTheta(15, E, A) \
35 | thetaRhoPiChiIotaPrepareTheta(16, A, E) \
36 | thetaRhoPiChiIotaPrepareTheta(17, E, A) \
37 | thetaRhoPiChiIotaPrepareTheta(18, A, E) \
38 | thetaRhoPiChiIotaPrepareTheta(19, E, A) \
39 | thetaRhoPiChiIotaPrepareTheta(20, A, E) \
40 | thetaRhoPiChiIotaPrepareTheta(21, E, A) \
41 | thetaRhoPiChiIotaPrepareTheta(22, A, E) \
42 | thetaRhoPiChiIota(23, E, A) \
43 |
44 | #define rounds12 \
45 | prepareTheta \
46 | thetaRhoPiChiIotaPrepareTheta(12, A, E) \
47 | thetaRhoPiChiIotaPrepareTheta(13, E, A) \
48 | thetaRhoPiChiIotaPrepareTheta(14, A, E) \
49 | thetaRhoPiChiIotaPrepareTheta(15, E, A) \
50 | thetaRhoPiChiIotaPrepareTheta(16, A, E) \
51 | thetaRhoPiChiIotaPrepareTheta(17, E, A) \
52 | thetaRhoPiChiIotaPrepareTheta(18, A, E) \
53 | thetaRhoPiChiIotaPrepareTheta(19, E, A) \
54 | thetaRhoPiChiIotaPrepareTheta(20, A, E) \
55 | thetaRhoPiChiIotaPrepareTheta(21, E, A) \
56 | thetaRhoPiChiIotaPrepareTheta(22, A, E) \
57 | thetaRhoPiChiIota(23, E, A) \
58 |
59 | #elif (Unrolling == 12)
60 | #define rounds24 \
61 | prepareTheta \
62 | for(i=0; i<24; i+=12) { \
63 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \
64 | thetaRhoPiChiIotaPrepareTheta(i+ 1, E, A) \
65 | thetaRhoPiChiIotaPrepareTheta(i+ 2, A, E) \
66 | thetaRhoPiChiIotaPrepareTheta(i+ 3, E, A) \
67 | thetaRhoPiChiIotaPrepareTheta(i+ 4, A, E) \
68 | thetaRhoPiChiIotaPrepareTheta(i+ 5, E, A) \
69 | thetaRhoPiChiIotaPrepareTheta(i+ 6, A, E) \
70 | thetaRhoPiChiIotaPrepareTheta(i+ 7, E, A) \
71 | thetaRhoPiChiIotaPrepareTheta(i+ 8, A, E) \
72 | thetaRhoPiChiIotaPrepareTheta(i+ 9, E, A) \
73 | thetaRhoPiChiIotaPrepareTheta(i+10, A, E) \
74 | thetaRhoPiChiIotaPrepareTheta(i+11, E, A) \
75 | } \
76 |
77 | #define rounds12 \
78 | prepareTheta \
79 | thetaRhoPiChiIotaPrepareTheta(12, A, E) \
80 | thetaRhoPiChiIotaPrepareTheta(13, E, A) \
81 | thetaRhoPiChiIotaPrepareTheta(14, A, E) \
82 | thetaRhoPiChiIotaPrepareTheta(15, E, A) \
83 | thetaRhoPiChiIotaPrepareTheta(16, A, E) \
84 | thetaRhoPiChiIotaPrepareTheta(17, E, A) \
85 | thetaRhoPiChiIotaPrepareTheta(18, A, E) \
86 | thetaRhoPiChiIotaPrepareTheta(19, E, A) \
87 | thetaRhoPiChiIotaPrepareTheta(20, A, E) \
88 | thetaRhoPiChiIotaPrepareTheta(21, E, A) \
89 | thetaRhoPiChiIotaPrepareTheta(22, A, E) \
90 | thetaRhoPiChiIota(23, E, A) \
91 |
92 | #elif (Unrolling == 6)
93 | #define rounds24 \
94 | prepareTheta \
95 | for(i=0; i<24; i+=6) { \
96 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \
97 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
98 | thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \
99 | thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \
100 | thetaRhoPiChiIotaPrepareTheta(i+4, A, E) \
101 | thetaRhoPiChiIotaPrepareTheta(i+5, E, A) \
102 | } \
103 |
104 | #define rounds12 \
105 | prepareTheta \
106 | for(i=12; i<24; i+=6) { \
107 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \
108 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
109 | thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \
110 | thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \
111 | thetaRhoPiChiIotaPrepareTheta(i+4, A, E) \
112 | thetaRhoPiChiIotaPrepareTheta(i+5, E, A) \
113 | } \
114 |
115 | #elif (Unrolling == 4)
116 | #define rounds24 \
117 | prepareTheta \
118 | for(i=0; i<24; i+=4) { \
119 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \
120 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
121 | thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \
122 | thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \
123 | } \
124 |
125 | #define rounds12 \
126 | prepareTheta \
127 | for(i=12; i<24; i+=4) { \
128 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \
129 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
130 | thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \
131 | thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \
132 | } \
133 |
134 | #elif (Unrolling == 3)
135 | #define rounds24 \
136 | prepareTheta \
137 | for(i=0; i<24; i+=3) { \
138 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \
139 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
140 | thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \
141 | copyStateVariables(A, E) \
142 | } \
143 |
144 | #define rounds12 \
145 | prepareTheta \
146 | for(i=12; i<24; i+=3) { \
147 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \
148 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
149 | thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \
150 | copyStateVariables(A, E) \
151 | } \
152 |
153 | #elif (Unrolling == 2)
154 | #define rounds24 \
155 | prepareTheta \
156 | for(i=0; i<24; i+=2) { \
157 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \
158 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
159 | } \
160 |
161 | #define rounds12 \
162 | prepareTheta \
163 | for(i=12; i<24; i+=2) { \
164 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \
165 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
166 | } \
167 |
168 | #elif (Unrolling == 1)
169 | #define rounds24 \
170 | prepareTheta \
171 | for(i=0; i<24; i++) { \
172 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \
173 | copyStateVariables(A, E) \
174 | } \
175 |
176 | #define rounds12 \
177 | prepareTheta \
178 | for(i=12; i<24; i++) { \
179 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \
180 | copyStateVariables(A, E) \
181 | } \
182 |
183 | #else
184 | #error "Unrolling is not correctly specified!"
185 | #endif
186 |
187 | #define roundsN(__nrounds) \
188 | prepareTheta \
189 | i = 24 - (__nrounds); \
190 | if ((i&1) != 0) { \
191 | thetaRhoPiChiIotaPrepareTheta(i, A, E) \
192 | copyStateVariables(A, E) \
193 | ++i; \
194 | } \
195 | for( /* empty */; i<24; i+=2) { \
196 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \
197 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
198 | }
199 |
--------------------------------------------------------------------------------
/src/sha3/keccak4x/KeccakP-1600-unrolling.txt:
--------------------------------------------------------------------------------
1 | /*
2 | Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni,
3 | Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby
4 | denoted as "the implementer".
5 |
6 | For more information, feedback or questions, please refer to our websites:
7 | http://keccak.noekeon.org/
8 | http://keyak.noekeon.org/
9 | http://ketje.noekeon.org/
10 |
11 | To the extent possible under law, the implementer has waived all copyright
12 | and related or neighboring rights to the source code in this file.
13 | http://creativecommons.org/publicdomain/zero/1.0/
14 | */
15 |
16 | #if (defined(FullUnrolling))
17 | #define rounds24 \
18 | prepareTheta \
19 | thetaRhoPiChiIotaPrepareTheta( 0, A, E) \
20 | thetaRhoPiChiIotaPrepareTheta( 1, E, A) \
21 | thetaRhoPiChiIotaPrepareTheta( 2, A, E) \
22 | thetaRhoPiChiIotaPrepareTheta( 3, E, A) \
23 | thetaRhoPiChiIotaPrepareTheta( 4, A, E) \
24 | thetaRhoPiChiIotaPrepareTheta( 5, E, A) \
25 | thetaRhoPiChiIotaPrepareTheta( 6, A, E) \
26 | thetaRhoPiChiIotaPrepareTheta( 7, E, A) \
27 | thetaRhoPiChiIotaPrepareTheta( 8, A, E) \
28 | thetaRhoPiChiIotaPrepareTheta( 9, E, A) \
29 | thetaRhoPiChiIotaPrepareTheta(10, A, E) \
30 | thetaRhoPiChiIotaPrepareTheta(11, E, A) \
31 | thetaRhoPiChiIotaPrepareTheta(12, A, E) \
32 | thetaRhoPiChiIotaPrepareTheta(13, E, A) \
33 | thetaRhoPiChiIotaPrepareTheta(14, A, E) \
34 | thetaRhoPiChiIotaPrepareTheta(15, E, A) \
35 | thetaRhoPiChiIotaPrepareTheta(16, A, E) \
36 | thetaRhoPiChiIotaPrepareTheta(17, E, A) \
37 | thetaRhoPiChiIotaPrepareTheta(18, A, E) \
38 | thetaRhoPiChiIotaPrepareTheta(19, E, A) \
39 | thetaRhoPiChiIotaPrepareTheta(20, A, E) \
40 | thetaRhoPiChiIotaPrepareTheta(21, E, A) \
41 | thetaRhoPiChiIotaPrepareTheta(22, A, E) \
42 | thetaRhoPiChiIota(23, E, A) \
43 |
44 | #define rounds12 \
45 | prepareTheta \
46 | thetaRhoPiChiIotaPrepareTheta(12, A, E) \
47 | thetaRhoPiChiIotaPrepareTheta(13, E, A) \
48 | thetaRhoPiChiIotaPrepareTheta(14, A, E) \
49 | thetaRhoPiChiIotaPrepareTheta(15, E, A) \
50 | thetaRhoPiChiIotaPrepareTheta(16, A, E) \
51 | thetaRhoPiChiIotaPrepareTheta(17, E, A) \
52 | thetaRhoPiChiIotaPrepareTheta(18, A, E) \
53 | thetaRhoPiChiIotaPrepareTheta(19, E, A) \
54 | thetaRhoPiChiIotaPrepareTheta(20, A, E) \
55 | thetaRhoPiChiIotaPrepareTheta(21, E, A) \
56 | thetaRhoPiChiIotaPrepareTheta(22, A, E) \
57 | thetaRhoPiChiIota(23, E, A) \
58 |
59 | #elif (Unrolling == 12)
60 | #define rounds24 \
61 | prepareTheta \
62 | for(i=0; i<24; i+=12) { \
63 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \
64 | thetaRhoPiChiIotaPrepareTheta(i+ 1, E, A) \
65 | thetaRhoPiChiIotaPrepareTheta(i+ 2, A, E) \
66 | thetaRhoPiChiIotaPrepareTheta(i+ 3, E, A) \
67 | thetaRhoPiChiIotaPrepareTheta(i+ 4, A, E) \
68 | thetaRhoPiChiIotaPrepareTheta(i+ 5, E, A) \
69 | thetaRhoPiChiIotaPrepareTheta(i+ 6, A, E) \
70 | thetaRhoPiChiIotaPrepareTheta(i+ 7, E, A) \
71 | thetaRhoPiChiIotaPrepareTheta(i+ 8, A, E) \
72 | thetaRhoPiChiIotaPrepareTheta(i+ 9, E, A) \
73 | thetaRhoPiChiIotaPrepareTheta(i+10, A, E) \
74 | thetaRhoPiChiIotaPrepareTheta(i+11, E, A) \
75 | } \
76 |
77 | #define rounds12 \
78 | prepareTheta \
79 | thetaRhoPiChiIotaPrepareTheta(12, A, E) \
80 | thetaRhoPiChiIotaPrepareTheta(13, E, A) \
81 | thetaRhoPiChiIotaPrepareTheta(14, A, E) \
82 | thetaRhoPiChiIotaPrepareTheta(15, E, A) \
83 | thetaRhoPiChiIotaPrepareTheta(16, A, E) \
84 | thetaRhoPiChiIotaPrepareTheta(17, E, A) \
85 | thetaRhoPiChiIotaPrepareTheta(18, A, E) \
86 | thetaRhoPiChiIotaPrepareTheta(19, E, A) \
87 | thetaRhoPiChiIotaPrepareTheta(20, A, E) \
88 | thetaRhoPiChiIotaPrepareTheta(21, E, A) \
89 | thetaRhoPiChiIotaPrepareTheta(22, A, E) \
90 | thetaRhoPiChiIota(23, E, A) \
91 |
92 | #elif (Unrolling == 6)
93 | #define rounds24 \
94 | prepareTheta \
95 | for(i=0; i<24; i+=6) { \
96 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \
97 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
98 | thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \
99 | thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \
100 | thetaRhoPiChiIotaPrepareTheta(i+4, A, E) \
101 | thetaRhoPiChiIotaPrepareTheta(i+5, E, A) \
102 | } \
103 |
104 | #define rounds12 \
105 | prepareTheta \
106 | for(i=12; i<24; i+=6) { \
107 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \
108 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
109 | thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \
110 | thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \
111 | thetaRhoPiChiIotaPrepareTheta(i+4, A, E) \
112 | thetaRhoPiChiIotaPrepareTheta(i+5, E, A) \
113 | } \
114 |
115 | #elif (Unrolling == 4)
116 | #define rounds24 \
117 | prepareTheta \
118 | for(i=0; i<24; i+=4) { \
119 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \
120 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
121 | thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \
122 | thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \
123 | } \
124 |
125 | #define rounds12 \
126 | prepareTheta \
127 | for(i=12; i<24; i+=4) { \
128 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \
129 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
130 | thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \
131 | thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \
132 | } \
133 |
134 | #elif (Unrolling == 3)
135 | #define rounds24 \
136 | prepareTheta \
137 | for(i=0; i<24; i+=3) { \
138 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \
139 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
140 | thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \
141 | copyStateVariables(A, E) \
142 | } \
143 |
144 | #define rounds12 \
145 | prepareTheta \
146 | for(i=12; i<24; i+=3) { \
147 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \
148 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
149 | thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \
150 | copyStateVariables(A, E) \
151 | } \
152 |
153 | #elif (Unrolling == 2)
154 | #define rounds24 \
155 | prepareTheta \
156 | for(i=0; i<24; i+=2) { \
157 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \
158 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
159 | } \
160 |
161 | #define rounds12 \
162 | prepareTheta \
163 | for(i=12; i<24; i+=2) { \
164 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \
165 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
166 | } \
167 |
168 | #elif (Unrolling == 1)
169 | #define rounds24 \
170 | prepareTheta \
171 | for(i=0; i<24; i++) { \
172 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \
173 | copyStateVariables(A, E) \
174 | } \
175 |
176 | #define rounds12 \
177 | prepareTheta \
178 | for(i=12; i<24; i++) { \
179 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \
180 | copyStateVariables(A, E) \
181 | } \
182 |
183 | #else
184 | #error "Unrolling is not correctly specified!"
185 | #endif
186 |
187 | #define roundsN(__nrounds) \
188 | prepareTheta \
189 | i = 24 - (__nrounds); \
190 | if ((i&1) != 0) { \
191 | thetaRhoPiChiIotaPrepareTheta(i, A, E) \
192 | copyStateVariables(A, E) \
193 | ++i; \
194 | } \
195 | for( /* empty */; i<24; i+=2) { \
196 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \
197 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
198 | }
199 |
--------------------------------------------------------------------------------
/src/sha3/keccak4x/SIMD256-config.h:
--------------------------------------------------------------------------------
1 | #define KeccakP1600times4_implementation_config "AVX2, all rounds unrolled"
2 | #define KeccakP1600times4_fullUnrolling
3 | #define KeccakP1600times4_useAVX2
4 |
--------------------------------------------------------------------------------
/src/sha3/keccak4x/align.h:
--------------------------------------------------------------------------------
1 | /*
2 | Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni,
3 | Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby
4 | denoted as "the implementer".
5 |
6 | For more information, feedback or questions, please refer to our websites:
7 | http://keccak.noekeon.org/
8 | http://keyak.noekeon.org/
9 | http://ketje.noekeon.org/
10 |
11 | To the extent possible under law, the implementer has waived all copyright
12 | and related or neighboring rights to the source code in this file.
13 | http://creativecommons.org/publicdomain/zero/1.0/
14 | */
15 |
16 | #ifndef _align_h_
17 | #define _align_h_
18 |
19 | /* on Mac OS-X and possibly others, ALIGN(x) is defined in param.h, and -Werror chokes on the redef. */
20 | #ifdef ALIGN
21 | #undef ALIGN
22 | #endif
23 |
24 | #if defined(__GNUC__)
25 | #define ALIGN(x) __attribute__ ((aligned(x)))
26 | #elif defined(_MSC_VER)
27 | #define ALIGN(x) __declspec(align(x))
28 | #elif defined(__ARMCC_VERSION)
29 | #define ALIGN(x) __align(x)
30 | #else
31 | #define ALIGN(x)
32 | #endif
33 |
34 | #endif
35 |
--------------------------------------------------------------------------------
/src/sha3/keccak4x/brg_endian.h:
--------------------------------------------------------------------------------
1 | /*
2 | ---------------------------------------------------------------------------
3 | Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
4 |
5 | LICENSE TERMS
6 |
7 | The redistribution and use of this software (with or without changes)
8 | is allowed without the payment of fees or royalties provided that:
9 |
10 | 1. source code distributions include the above copyright notice, this
11 | list of conditions and the following disclaimer;
12 |
13 | 2. binary distributions include the above copyright notice, this list
14 | of conditions and the following disclaimer in their documentation;
15 |
16 | 3. the name of the copyright holder is not used to endorse products
17 | built using this software without specific written permission.
18 |
19 | DISCLAIMER
20 |
21 | This software is provided 'as is' with no explicit or implied warranties
22 | in respect of its properties, including, but not limited to, correctness
23 | and/or fitness for purpose.
24 | ---------------------------------------------------------------------------
25 | Issue Date: 20/12/2007
26 | Changes for ARM 9/9/2010
27 | */
28 |
29 | #ifndef _BRG_ENDIAN_H
30 | #define _BRG_ENDIAN_H
31 |
32 | #define IS_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */
33 | #define IS_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */
34 |
35 | #if 0
36 | /* Include files where endian defines and byteswap functions may reside */
37 | #if defined( __sun )
38 | # include
39 | #elif defined( __FreeBSD__ ) || defined( __OpenBSD__ ) || defined( __NetBSD__ )
40 | # include
41 | #elif defined( BSD ) && ( BSD >= 199103 ) || defined( __APPLE__ ) || \
42 | defined( __CYGWIN32__ ) || defined( __DJGPP__ ) || defined( __osf__ )
43 | # include
44 | #elif defined( __linux__ ) || defined( __GNUC__ ) || defined( __GNU_LIBRARY__ )
45 | # if !defined( __MINGW32__ ) && !defined( _AIX )
46 | # include
47 | # if !defined( __BEOS__ )
48 | # include
49 | # endif
50 | # endif
51 | #endif
52 | #endif
53 |
54 | /* Now attempt to set the define for platform byte order using any */
55 | /* of the four forms SYMBOL, _SYMBOL, __SYMBOL & __SYMBOL__, which */
56 | /* seem to encompass most endian symbol definitions */
57 |
58 | #if defined( BIG_ENDIAN ) && defined( LITTLE_ENDIAN )
59 | # if defined( BYTE_ORDER ) && BYTE_ORDER == BIG_ENDIAN
60 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
61 | # elif defined( BYTE_ORDER ) && BYTE_ORDER == LITTLE_ENDIAN
62 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
63 | # endif
64 | #elif defined( BIG_ENDIAN )
65 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
66 | #elif defined( LITTLE_ENDIAN )
67 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
68 | #endif
69 |
70 | #if defined( _BIG_ENDIAN ) && defined( _LITTLE_ENDIAN )
71 | # if defined( _BYTE_ORDER ) && _BYTE_ORDER == _BIG_ENDIAN
72 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
73 | # elif defined( _BYTE_ORDER ) && _BYTE_ORDER == _LITTLE_ENDIAN
74 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
75 | # endif
76 | #elif defined( _BIG_ENDIAN )
77 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
78 | #elif defined( _LITTLE_ENDIAN )
79 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
80 | #endif
81 |
82 | #if defined( __BIG_ENDIAN ) && defined( __LITTLE_ENDIAN )
83 | # if defined( __BYTE_ORDER ) && __BYTE_ORDER == __BIG_ENDIAN
84 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
85 | # elif defined( __BYTE_ORDER ) && __BYTE_ORDER == __LITTLE_ENDIAN
86 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
87 | # endif
88 | #elif defined( __BIG_ENDIAN )
89 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
90 | #elif defined( __LITTLE_ENDIAN )
91 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
92 | #endif
93 |
94 | #if defined( __BIG_ENDIAN__ ) && defined( __LITTLE_ENDIAN__ )
95 | # if defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __BIG_ENDIAN__
96 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
97 | # elif defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __LITTLE_ENDIAN__
98 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
99 | # endif
100 | #elif defined( __BIG_ENDIAN__ )
101 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
102 | #elif defined( __LITTLE_ENDIAN__ )
103 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
104 | #endif
105 |
106 | /* if the platform byte order could not be determined, then try to */
107 | /* set this define using common machine defines */
108 | #if !defined(PLATFORM_BYTE_ORDER)
109 |
110 | #if defined( __alpha__ ) || defined( __alpha ) || defined( i386 ) || \
111 | defined( __i386__ ) || defined( _M_I86 ) || defined( _M_IX86 ) || \
112 | defined( __OS2__ ) || defined( sun386 ) || defined( __TURBOC__ ) || \
113 | defined( vax ) || defined( vms ) || defined( VMS ) || \
114 | defined( __VMS ) || defined( _M_X64 )
115 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
116 |
117 | #elif defined( AMIGA ) || defined( applec ) || defined( __AS400__ ) || \
118 | defined( _CRAY ) || defined( __hppa ) || defined( __hp9000 ) || \
119 | defined( ibm370 ) || defined( mc68000 ) || defined( m68k ) || \
120 | defined( __MRC__ ) || defined( __MVS__ ) || defined( __MWERKS__ ) || \
121 | defined( sparc ) || defined( __sparc) || defined( SYMANTEC_C ) || \
122 | defined( __VOS__ ) || defined( __TIGCC__ ) || defined( __TANDEM ) || \
123 | defined( THINK_C ) || defined( __VMCMS__ ) || defined( _AIX )
124 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
125 |
126 | #elif defined(__arm__)
127 | # ifdef __BIG_ENDIAN
128 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
129 | # else
130 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
131 | # endif
132 | #elif 1 /* **** EDIT HERE IF NECESSARY **** */
133 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
134 | #elif 0 /* **** EDIT HERE IF NECESSARY **** */
135 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
136 | #else
137 | # error Please edit lines 132 or 134 in brg_endian.h to set the platform byte order
138 | #endif
139 |
140 | #endif
141 |
142 | #endif
143 |
--------------------------------------------------------------------------------
/tests/ds_benchmark.h:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * ds_benchmark.h: Macros for simple benchmarking of C code.
3 | *
4 | * See instructions for usage below.
5 | * Software originally developed by Douglas Stebila.
6 | * Most recent version at https://gist.github.com/dstebila/6980008ec98209ef6075
7 | *
8 | * This is free and unencumbered software released into the public domain.
9 | *
10 | * Anyone is free to copy, modify, publish, use, compile, sell, or
11 | * distribute this software, either in source code form or as a compiled
12 | * binary, for any purpose, commercial or non-commercial, and by any
13 | * means.
14 | *
15 | * In jurisdictions that recognize copyright laws, the author or authors
16 | * of this software dedicate any and all copyright interest in the
17 | * software to the public domain. We make this dedication for the benefit
18 | * of the public at large and to the detriment of our heirs and
19 | * successors. We intend this dedication to be an overt act of
20 | * relinquishment in perpetuity of all present and future rights to this
21 | * software under copyright law.
22 | *
23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
26 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
27 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
28 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
29 | * OTHER DEALINGS IN THE SOFTWARE.
30 | *
31 | * For more information, please refer to
32 | ********************************************************************************************/
33 |
34 | /** \file ds_benchmark.h
35 | * Macros for simple benchmarking of C code.
36 | */
37 |
38 | #ifndef _DS_BENCHMARK_H
39 | #define _DS_BENCHMARK_H
40 |
41 | #include "../src/frodo.h"
42 | #include
43 | #include
44 | #include
45 | #if (OS_TARGET == OS_LINUX)
46 | #include
47 | #endif
48 | #include
49 | #include
50 |
51 |
52 | #if (OS_TARGET == OS_WIN)
53 | #include
54 |
55 | int gettimeofday(struct timeval *tp, struct timezone *tzp) {
56 | // Note: some broken versions only have 8 trailing zero's, the correct epoch has 9 trailing zero's
57 | static const uint64_t EPOCH = ((uint64_t)116444736000000000ULL);
58 |
59 | SYSTEMTIME system_time;
60 | FILETIME file_time;
61 | uint64_t time;
62 |
63 | GetSystemTime(&system_time);
64 | SystemTimeToFileTime(&system_time, &file_time);
65 | time = ((uint64_t)file_time.dwLowDateTime);
66 | time += ((uint64_t)file_time.dwHighDateTime) << 32;
67 |
68 | tp->tv_sec = (long)((time - EPOCH) / 10000000L);
69 | tp->tv_usec = (long)(system_time.wMilliseconds * 1000);
70 | return 0;
71 | }
72 | #endif
73 |
74 |
75 | static uint64_t rdtsc(void) {
76 | #if (OS_TARGET == OS_WIN)
77 | return __rdtsc();
78 | #elif (OS_TARGET == OS_LINUX) && (TARGET == TARGET_AMD64 || TARGET == TARGET_x86)
79 | uint64_t x;
80 | __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
81 | return x;
82 | #elif (OS_TARGET == OS_LINUX && TARGET == TARGET_ARM)
83 | struct timespec time;
84 | clock_gettime(CLOCK_REALTIME, &time);
85 | return (int64_t)(time.tv_sec*1e9 + time.tv_nsec);
86 | #else
87 | return 0;
88 | #endif
89 | }
90 |
91 |
92 | #define DEFINE_TIMER_VARIABLES \
93 | volatile uint64_t _bench_cycles_start, _bench_cycles_end; \
94 | uint64_t _bench_cycles_cumulative = 0; \
95 | int64_t _bench_cycles_diff; \
96 | struct timeval _bench_timeval_start, _bench_timeval_end; \
97 | uint64_t _bench_iterations, _bench_time_cumulative; \
98 | double _bench_cycles_x, _bench_cycles_mean, _bench_cycles_delta, _bench_cycles_M2, _bench_cycles_stdev; \
99 | double _bench_time_x, _bench_time_mean, _bench_time_delta, _bench_time_M2, _bench_time_stdev;
100 |
101 | #define INITIALIZE_TIMER \
102 | _bench_iterations = 0; \
103 | _bench_cycles_mean = 0.0; \
104 | _bench_cycles_M2 = 0.0; \
105 | _bench_time_cumulative = 0; \
106 | _bench_time_mean = 0.0; \
107 | _bench_time_M2 = 0.0;
108 |
109 | #define START_TIMER \
110 | gettimeofday(&_bench_timeval_start, NULL); \
111 | _bench_cycles_start = rdtsc();
112 |
113 |
114 | // Mean and population standard deviation are calculated in an online way using the algorithm in
115 | // http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Online_algorithm
116 |
117 | #define STOP_TIMER \
118 | _bench_cycles_end = rdtsc(); \
119 | gettimeofday(&_bench_timeval_end, NULL); \
120 | _bench_iterations += 1; \
121 | if (_bench_cycles_end < _bench_cycles_start) { _bench_cycles_end += 1UL << 32; } \
122 | _bench_cycles_diff = _bench_cycles_end; \
123 | _bench_cycles_diff -= _bench_cycles_start; \
124 | _bench_cycles_cumulative += _bench_cycles_diff; \
125 | _bench_cycles_x = (double) (_bench_cycles_diff); \
126 | _bench_cycles_delta = _bench_cycles_x - _bench_cycles_mean; \
127 | _bench_cycles_mean += _bench_cycles_delta / (double) _bench_iterations; \
128 | _bench_cycles_M2 += _bench_cycles_delta * (_bench_cycles_x - _bench_cycles_mean); \
129 | _bench_time_x = (double) ((_bench_timeval_end.tv_sec * 1000000 + _bench_timeval_end.tv_usec) - (_bench_timeval_start.tv_sec * 1000000 + _bench_timeval_start.tv_usec)); \
130 | _bench_time_delta = _bench_time_x - _bench_time_mean; \
131 | _bench_time_mean += _bench_time_delta / (double) _bench_iterations; \
132 | _bench_time_M2 += _bench_time_delta * (_bench_time_x - _bench_time_mean); \
133 | _bench_time_cumulative += _bench_time_x;
134 |
135 | #define FINALIZE_TIMER \
136 | if (_bench_iterations == 2) { _bench_cycles_stdev = 0.0; } \
137 | else { _bench_cycles_stdev = sqrt(_bench_cycles_M2 / (double) _bench_iterations); } \
138 | if (_bench_iterations == 2) { _bench_time_stdev = 0.0; } \
139 | else { _bench_time_stdev = sqrt(_bench_time_M2 / (double) _bench_iterations); }
140 |
141 | #define PRINT_CURRENT_TIME \
142 | { \
143 | char _bench_time_buff[20]; \
144 | time_t _bench_time_now = time(0); \
145 | strftime(_bench_time_buff, 20, "%Y-%m-%d %H:%M:%S", localtime (&_bench_time_now)); \
146 | printf("%s", _bench_time_buff); \
147 | }
148 |
149 | #define PRINT_TIMER_HEADER \
150 | printf("Started at "); \
151 | PRINT_CURRENT_TIME \
152 | printf("\n"); \
153 | printf("%-30s %15s %15s %15s %15s %15s %15s\n", "Operation", "Iterations", "Total time (s)", "Time(us): mean", "pop. stdev", "Cycles: mean", "pop. stdev");
154 |
155 | #define PRINT_TIMER_FOOTER \
156 | printf("Ended at "); \
157 | PRINT_CURRENT_TIME \
158 | printf("\n");
159 |
160 | #define PRINT_TIMER_AVG(op_name) \
161 | printf("%-30s %15" PRIu64 " %15.3f %15.3f %15.3f %15.0f %15.0f\n", (op_name), _bench_iterations, ((double) _bench_time_cumulative) / 1000000.0, _bench_time_mean, _bench_time_stdev, ((double) _bench_cycles_cumulative) / (double) _bench_iterations, _bench_cycles_stdev);
162 |
163 | #define TIME_OPERATION_ITERATIONS(op, op_name, it) \
164 | { \
165 | DEFINE_TIMER_VARIABLES \
166 | INITIALIZE_TIMER \
167 | for (int i = 0; i < (it); i++) { \
168 | START_TIMER \
169 | { op ; } \
170 | STOP_TIMER \
171 | } \
172 | FINALIZE_TIMER \
173 | PRINT_TIMER_AVG(op_name) \
174 | }
175 |
176 | #define TIME_OPERATION_SECONDS(op, op_name, secs) \
177 | { \
178 | DEFINE_TIMER_VARIABLES \
179 | INITIALIZE_TIMER \
180 | uint64_t _bench_time_goal_usecs = 1000000 * secs; \
181 | while (_bench_time_cumulative < _bench_time_goal_usecs) { \
182 | START_TIMER \
183 | { op ; } \
184 | STOP_TIMER \
185 | } \
186 | FINALIZE_TIMER \
187 | PRINT_TIMER_AVG(op_name) \
188 | }
189 | #endif
190 |
--------------------------------------------------------------------------------
/tests/test_kex.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include "../src/random/rand.h"
6 | #include "../src/kex.h"
7 | #include "ds_benchmark.h"
8 |
9 |
10 | struct kex_testcase {
11 | enum OQS_KEX_alg_name alg_name;
12 | unsigned char *seed;
13 | size_t seed_len;
14 | char *named_parameters;
15 | char *id;
16 | int run;
17 | };
18 |
19 |
20 | /* Add new testcases here */
21 | struct kex_testcase kex_testcases[] = {
22 | { OQS_KEX_alg_lwe_frodo, (unsigned char*)"01234567890123456", 16, "recommended", "lwe_frodo_recommended", 0 },
23 | };
24 |
25 |
26 | #define KEX_TEST_ITERATIONS 100
27 | #define KEX_BENCH_SECONDS 1
28 |
29 | #define PRINT_HEX_STRING(label, str, len) { \
30 | printf("%-20s (%4zu bytes): ", (label), (size_t) (len)); \
31 | for (size_t i = 0; i < (len); i++) { \
32 | printf("%02X", ((unsigned char *) (str)) [i]); \
33 | } \
34 | printf("\n"); \
35 | }
36 |
37 |
38 | static int kex_test_correctness(OQS_RAND *rand, enum OQS_KEX_alg_name alg_name, const uint8_t *seed, const size_t seed_len, const char *named_parameters, const int print, unsigned long occurrences[256])
39 | {
40 | OQS_KEX *kex = NULL;
41 | int rc;
42 |
43 | void *alice_priv = NULL;
44 | uint8_t *alice_msg = NULL;
45 | size_t alice_msg_len;
46 | uint8_t *alice_key = NULL;
47 | size_t alice_key_len;
48 |
49 | uint8_t *bob_msg = NULL;
50 | size_t bob_msg_len;
51 | uint8_t *bob_key = NULL;
52 | size_t bob_key_len;
53 |
54 |
55 | //uint8_t in1[32], in2[32];
56 | //uint32_t out1[64];
57 |
58 |
59 | /* setup KEX */
60 | kex = OQS_KEX_new(rand, alg_name, seed, seed_len, named_parameters);
61 | if (kex == NULL) {
62 | fprintf(stderr, "new_method failed\n");
63 | goto err;
64 | }
65 |
66 | if (print) {
67 | printf("================================================================================\n");
68 | printf("Sample computation for key exchange method %s\n", kex->method_name);
69 | printf("================================================================================\n");
70 | }
71 |
72 | /* Alice's initial message */
73 | rc = OQS_KEX_alice_0(kex, &alice_priv, &alice_msg, &alice_msg_len);
74 | if (rc != 1) {
75 | fprintf(stderr, "OQS_KEX_alice_0 failed\n");
76 | goto err;
77 | }
78 |
79 | if (print) {
80 | PRINT_HEX_STRING("Alice message", alice_msg, alice_msg_len)
81 | }
82 |
83 | /* Bob's response */
84 | rc = OQS_KEX_bob(kex, alice_msg, alice_msg_len, &bob_msg, &bob_msg_len, &bob_key, &bob_key_len);
85 | if (rc != 1) {
86 | fprintf(stderr, "OQS_KEX_bob failed\n");
87 | goto err;
88 | }
89 |
90 | if (print) {
91 | PRINT_HEX_STRING("Bob message", bob_msg, bob_msg_len)
92 | PRINT_HEX_STRING("Bob session key", bob_key, bob_key_len)
93 | }
94 |
95 | /* Alice processes Bob's response */
96 | rc = OQS_KEX_alice_1(kex, alice_priv, bob_msg, bob_msg_len, &alice_key, &alice_key_len);
97 | if (rc != 1) {
98 | fprintf(stderr, "OQS_KEX_alice_1 failed\n");
99 | goto err;
100 | }
101 |
102 | if (print) {
103 | PRINT_HEX_STRING("Alice session key", alice_key, alice_key_len)
104 | }
105 |
106 | /* compare session key lengths and values */
107 | if (alice_key_len != bob_key_len) {
108 | fprintf(stderr, "ERROR: Alice's session key and Bob's session key are different lengths (%zu vs %zu)\n", alice_key_len, bob_key_len);
109 | goto err;
110 | }
111 | rc = memcmp(alice_key, bob_key, alice_key_len);
112 | if (rc != 0) {
113 | fprintf(stderr, "ERROR: Alice's session key and Bob's session key are not equal\n");
114 | PRINT_HEX_STRING("Alice session key", alice_key, alice_key_len)
115 | PRINT_HEX_STRING("Bob session key", bob_key, bob_key_len)
116 | goto err;
117 | }
118 | if (print) {
119 | printf("Alice and Bob's session keys match.\n");
120 | printf("\n\n");
121 | }
122 |
123 | /* record generated bytes for statistical analysis */
124 | for (size_t i = 0; i < alice_key_len; i++) {
125 | OQS_RAND_test_record_occurrence(alice_key[i], occurrences);
126 | }
127 |
128 | rc = 1;
129 | goto cleanup;
130 |
131 | err:
132 | rc = 0;
133 |
134 | cleanup:
135 | free(alice_msg);
136 | free(alice_key);
137 | free(bob_msg);
138 | free(bob_key);
139 | OQS_KEX_alice_priv_free(kex, alice_priv);
140 | OQS_KEX_free(kex);
141 |
142 | return rc;
143 | }
144 |
145 |
146 | static int kex_test_correctness_wrapper(OQS_RAND *rand, enum OQS_KEX_alg_name alg_name, const uint8_t *seed, const size_t seed_len, const char *named_parameters, int iterations)
147 | {
148 | OQS_KEX *kex = NULL;
149 | unsigned long occurrences[256] = {0};
150 | int ret;
151 |
152 | /* setup KEX */
153 | kex = OQS_KEX_new(rand, alg_name, seed, seed_len, named_parameters);
154 | if (kex == NULL) {
155 | goto err;
156 | }
157 |
158 | printf("==========================================================================================================================================\n");
159 | printf("Testing correctness and randomness of key exchange method %s (params=%s) for %d iterations\n",
160 | kex->method_name, named_parameters, iterations);
161 | printf("==========================================================================================================================================\n");
162 | for (int i = 0; i < iterations; i++) {
163 | ret = kex_test_correctness(rand, alg_name, seed, seed_len, named_parameters, 0, occurrences);
164 | if (ret != 1) {
165 | goto err;
166 | }
167 | }
168 | printf("Tests PASSED. All session keys matched.\n");
169 | printf("Statistical distance from uniform: %12.10f\n", OQS_RAND_test_statistical_distance_from_uniform(occurrences));
170 | printf("\n\n");
171 |
172 | ret = 1;
173 | goto cleanup;
174 |
175 | err:
176 | ret = 0;
177 |
178 | cleanup:
179 | OQS_KEX_free(kex);
180 |
181 | return ret;
182 | }
183 |
184 |
185 | static void cleanup_alice_0(OQS_KEX *kex, void *alice_priv, uint8_t *alice_msg)
186 | {
187 | free(alice_msg);
188 | OQS_KEX_alice_priv_free(kex, alice_priv);
189 | }
190 |
191 |
192 | static void cleanup_bob(uint8_t *bob_msg, uint8_t *bob_key)
193 | {
194 | free(bob_msg);
195 | free(bob_key);
196 | }
197 |
198 |
199 | static int kex_bench_wrapper(OQS_RAND *rand, enum OQS_KEX_alg_name alg_name, const uint8_t *seed, const size_t seed_len, const char *named_parameters, const int seconds)
200 | {
201 | OQS_KEX *kex = NULL;
202 | int rc;
203 |
204 | void *alice_priv = NULL;
205 | uint8_t *alice_msg = NULL;
206 | size_t alice_msg_len;
207 | uint8_t *alice_key = NULL;
208 | size_t alice_key_len;
209 |
210 | uint8_t *bob_msg = NULL;
211 | size_t bob_msg_len;
212 | uint8_t *bob_key = NULL;
213 | size_t bob_key_len;
214 |
215 | /* setup KEX */
216 | kex = OQS_KEX_new(rand, alg_name, seed, seed_len, named_parameters);
217 | if (kex == NULL) {
218 | fprintf(stderr, "new_method failed\n");
219 | goto err;
220 | }
221 | printf("%s\n", kex->method_name);
222 |
223 | TIME_OPERATION_SECONDS({ OQS_KEX_alice_0(kex, &alice_priv, &alice_msg, &alice_msg_len); cleanup_alice_0(kex, alice_priv, alice_msg); }, "alice 0", seconds);
224 |
225 | OQS_KEX_alice_0(kex, &alice_priv, &alice_msg, &alice_msg_len);
226 | TIME_OPERATION_SECONDS({ OQS_KEX_bob(kex, alice_msg, alice_msg_len, &bob_msg, &bob_msg_len, &bob_key, &bob_key_len); cleanup_bob(bob_msg, bob_key); }, "bob", seconds);
227 |
228 | OQS_KEX_bob(kex, alice_msg, alice_msg_len, &bob_msg, &bob_msg_len, &bob_key, &bob_key_len);
229 | TIME_OPERATION_SECONDS({ OQS_KEX_alice_1(kex, alice_priv, bob_msg, bob_msg_len, &alice_key, &alice_key_len); free(alice_key); }, "alice 1", seconds);
230 | alice_key = NULL;
231 |
232 | rc = 1;
233 | goto cleanup;
234 |
235 | err:
236 | rc = 0;
237 |
238 | cleanup:
239 | free(alice_msg);
240 | free(alice_key);
241 | free(bob_msg);
242 | free(bob_key);
243 | OQS_KEX_alice_priv_free(kex, alice_priv);
244 | OQS_KEX_free(kex);
245 |
246 | return rc;
247 | }
248 |
249 |
250 | int main(int argc, char **argv)
251 | {
252 | int success = 1;
253 | bool run_all = true;
254 | size_t kex_testcases_len = sizeof(kex_testcases) / sizeof(struct kex_testcase);
255 |
256 | if (argc > 1) {
257 | if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "-help") == 0) || (strcmp(argv[1], "--help") == 0)) {
258 | printf("Usage: ./test_kex [algorithms]\n\n");
259 | printf("algorithms:\n");
260 | for (size_t i = 0; i < kex_testcases_len; i++) {
261 | printf(" %s\n", kex_testcases[i].id);
262 | }
263 | return EXIT_SUCCESS;
264 | }
265 | run_all = false;
266 | for (int i = 1; i < argc; i++) {
267 | for (size_t j = 0; j < kex_testcases_len; j++) {
268 | if (strcmp(argv[i], kex_testcases[j].id) == 0) {
269 | kex_testcases[j].run = 1;
270 | }
271 | }
272 | }
273 | }
274 |
275 | /* setup RAND */
276 | OQS_RAND *rand = OQS_RAND_new(OQS_RAND_alg_urandom_aesctr);
277 | if (rand == NULL) {
278 | goto err;
279 | }
280 |
281 | for (size_t i = 0; i < kex_testcases_len; i++) {
282 | if (run_all || kex_testcases[i].run == 1) {
283 | int num_iter = KEX_TEST_ITERATIONS;
284 | success = kex_test_correctness_wrapper(rand, kex_testcases[i].alg_name, kex_testcases[i].seed, kex_testcases[i].seed_len, kex_testcases[i].named_parameters, num_iter);
285 | }
286 | if (success != 1) {
287 | goto err;
288 | }
289 | }
290 |
291 | PRINT_TIMER_HEADER
292 | for (size_t i = 0; i < kex_testcases_len; i++) {
293 | if (run_all || kex_testcases[i].run == 1) {
294 | kex_bench_wrapper(rand, kex_testcases[i].alg_name, kex_testcases[i].seed, kex_testcases[i].seed_len, kex_testcases[i].named_parameters, KEX_BENCH_SECONDS);
295 | }
296 | }
297 | PRINT_TIMER_FOOTER
298 |
299 | success = 1;
300 | goto cleanup;
301 |
302 | err:
303 | success = 0;
304 | fprintf(stderr, "ERROR!\n");
305 |
306 | cleanup:
307 | OQS_RAND_free(rand);
308 |
309 | return (success == 1) ? EXIT_SUCCESS : EXIT_FAILURE;
310 | }
311 |
--------------------------------------------------------------------------------