├── .gitignore ├── CONTRIBUTIONS ├── HOWTO.txt ├── INSTALL ├── LICENSE ├── Makefile.am ├── README.md ├── TODO.txt ├── bootstrap.sh ├── configure.ac ├── doc └── spec ├── preamble ├── src ├── Makefile.am ├── fnr.c └── fnr.h └── test ├── Makefile.am ├── bench.c ├── generate_ipv4.py ├── raw-ips ├── raw-timestamps ├── test_ipv4.c └── test_timestamp.c /.gitignore: -------------------------------------------------------------------------------- 1 | compile 2 | autom4te.cache 3 | Makefile 4 | Makefile.in 5 | aclocal.m4 6 | app.info 7 | ar-lib 8 | config.guess 9 | config.h 10 | config.h.in 11 | config.log 12 | config.status 13 | config.sub 14 | configure 15 | configure.scan 16 | coverage_report 17 | depcomp 18 | install-sh 19 | libtool 20 | ltmain.sh 21 | m4 22 | missing 23 | stamp-h? 24 | *~ 25 | old 26 | old? 27 | *.html 28 | *.log 29 | *.o 30 | *.la 31 | *.so* 32 | *.dll 33 | *.dylib 34 | *.a 35 | *.lib 36 | .deps 37 | *.tar* 38 | *.zip 39 | *.lo 40 | *.gcno 41 | *.gcda 42 | *.exe 43 | *.out 44 | *.app 45 | .libs 46 | src/fnr 47 | test/cctest 48 | test/ipv4test 49 | test/timestamptest 50 | test/bench 51 | -------------------------------------------------------------------------------- /CONTRIBUTIONS: -------------------------------------------------------------------------------- 1 | Core design and Development 2 | --------------------------- 3 | Scott Fluhrer, Cisco Systems, Inc. 4 | Sashank Dara, Cisco Systems, Inc. 5 | 6 | Demo Applications 7 | ------------------ 8 | IP Addresses - Kaushal Bhandankar, Cisco Systems, Inc. 9 | Time Stamps - Anand Verma, verma.anand09@gmail.com 10 | - Prakruti C , prakruti c 11 | 12 | Code Review 13 | ------------ 14 | Olve Maudal, Cisco Systems, Inc. 15 | Anand Verma, Cisco Systems, Inc. 16 | 17 | Bug fixes 18 | --------- 19 | Abhishek Singh, Cisco Systems, Inc. 20 | Anand Verma, Cisco Systems, Inc. 21 | Jeff Squyres, Cisco Systems, Inc. 22 | 23 | Shared Object generations 24 | -------- 25 | Narasimha Datta Nataraja, Cisco Systems, Inc. 26 | -------------------------------------------------------------------------------- /HOWTO.txt: -------------------------------------------------------------------------------- 1 | libFNR is a utility to do small block encryption, with a variable sized block 2 | between 1 and 128 bits, and with no ciphertext expansion (that is, the 3 | ciphertext is precisely the same length as the plaintext) 4 | 5 | It isn't very efficient (it's not; after all, every encryption or decryption 6 | operation involves 7 calls to AES); it is designed to be secure. 7 | 8 | Here are the concepts behind it: 9 | - key -- This is the secret used to specify how to transform. This is the 10 | part that you share between the encryptor and decryptor, and what 11 | needs to be kept secret from anyone listening in. We use the same 12 | key sizes as AES (128, 192, 256 bits; expressed as a byte string). 13 | 14 | - tweak -- This is a parameter that modifies how the encryption is done. 15 | This is designed so that the same key can be used to protect 16 | different fields, in such a way so that if someone learns that 17 | plaintext xxx corresponds to ciphertext yyy in context A, they still 18 | have no information what yyy means in context B. The idea is that 19 | you'd use a string the identifies the context as the tweak. As such, 20 | the tweak has the following properties: 1) the encryption process 21 | with the same key and two different tweaks are unrelated; 2) there is 22 | no security problem with making the tweak public (unlike the key), 23 | 3) the tweak is cheap to update (a lot cheaper than the key, in this 24 | case) 25 | 26 | We support arbitrary bytestrings as tweaks 27 | 28 | - plaintext/ciphertext -- These are n-bit binary fields, with n being 29 | between 1 and 128 (and you specify it while expanding the key). 30 | These are represented by strings of unsigned char's, with each 31 | unsigned char holding 8 bits. If n is not a multiple of 8, then we 32 | handle the last partial byte by using the lsbits in the last byte; 33 | the msbits of that unsigned char are assumed not to be a part of the 34 | plaintext/ciphertext 35 | 36 | Now, encryption/decryption is deterministic; if we encrypt the same 37 | plaintext twice with the same key and tweak, you will always get the same 38 | ciphertext. This is a side effect of not having any ciphertext expansion, 39 | there are 2N possible plaintexts and 2N possible ciphertexts, and so 40 | (for a fixed key/tweak) there has to be a 1:1 mapping. 41 | 42 | Here's how you use it: 43 | 44 | Step 1: convert your key (128, 192 or 256 bit -- this is based on AES, and 45 | this key will be directly fed to it) into expanded form: 46 | 47 | fnr_expanded_key key = FNR_expand_key( aes_key, aes_key_size, 48 | block_size ); 49 | if (!key) error_handling(); 50 | 51 | The block_size parameter is the of blocks we'll encrypt with this key; it 52 | must be a value between 1 and 128 bits. Why anyone would want to encrypt 53 | a 1 bit block, I have no idea, but still... 54 | 55 | You can reuse this key every time you need to encrypt or decrypt with this 56 | key and this block size. If you want to use the same key with a different 57 | block size, that's fine (that won't cause a security problem), but you'll 58 | need to re-expand the key 59 | 60 | Step 2: expand your tweak (which is public data that modifies how the 61 | encryption is done; one way of thinking of this is to look at it as another 62 | part of the key, but one which can be made public, and which is cheap to 63 | change): 64 | 65 | fnr_expanded_tweak tweak; 66 | FNR_expand_tweak(&tweak, key, arbitrary_bytestring, length_of_bytestring); 67 | 68 | The tweak may consist of an arbitrary bytestring. 69 | 70 | If you use the same tweak for multiple encryptions/decryptions, you can use 71 | the same expanded tweak. 72 | 73 | If you don't have a tweak, you need to expand a 0-length tweak. Perhaps we 74 | could have the encrypt/decrypt routines interpret a NULL tweak as the 75 | 0-length; we currently don't bother (as 0-length tweaks may not occur often 76 | enough) 77 | 78 | Step 3: encrypt and decrypt your data 79 | 80 | FNR_encrypt(key, &tweak, plaintext, ciphertext); 81 | FNR_decrypt(key, &tweak, ciphertext, plaintext); 82 | 83 | Encrypting/decrypting in place (plaintext==ciphertext) is allowed; because 84 | the plaintext and the ciphertext are the same size, you may want to do this 85 | 86 | Here, plaintext and ciphertext are the number of bits long you specified 87 | when you expanded the key. Now, if you specified a length that's not a 88 | multiple of 8, here's how we handle that case: if you specify such an odd 89 | size N, we take all the N/8 bytes, plus the remaining N%8 lsbits from the 90 | next byte. When we write, we are careful not to disturb any bits outside the 91 | N bit region. For example, if we have a 4 bit ciphertext, we'll update the 92 | lower 4 bits of ciphertext, and leave the remaining upper 4 bits 93 | undisturbed. 94 | 95 | Step last: when you're done with the key, you discard it with: 96 | 97 | FNR_zeroize_key(key); 98 | FNR_shut(); 99 | 100 | (there's no need to zeroize the expanded tweak) 101 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | Installation Instructions 2 | ************************* 3 | 4 | Copyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation, 5 | Inc. 6 | 7 | Copying and distribution of this file, with or without modification, 8 | are permitted in any medium without royalty provided the copyright 9 | notice and this notice are preserved. This file is offered as-is, 10 | without warranty of any kind. 11 | 12 | Basic Installation 13 | ================== 14 | 15 | Briefly, the shell commands `./configure; make; make install' should 16 | configure, build, and install this package. The following 17 | more-detailed instructions are generic; see the `README' file for 18 | instructions specific to this package. Some packages provide this 19 | `INSTALL' file but do not implement all of the features documented 20 | below. The lack of an optional feature in a given package is not 21 | necessarily a bug. More recommendations for GNU packages can be found 22 | in *note Makefile Conventions: (standards)Makefile Conventions. 23 | 24 | The `configure' shell script attempts to guess correct values for 25 | various system-dependent variables used during compilation. It uses 26 | those values to create a `Makefile' in each directory of the package. 27 | It may also create one or more `.h' files containing system-dependent 28 | definitions. Finally, it creates a shell script `config.status' that 29 | you can run in the future to recreate the current configuration, and a 30 | file `config.log' containing compiler output (useful mainly for 31 | debugging `configure'). 32 | 33 | It can also use an optional file (typically called `config.cache' 34 | and enabled with `--cache-file=config.cache' or simply `-C') that saves 35 | the results of its tests to speed up reconfiguring. Caching is 36 | disabled by default to prevent problems with accidental use of stale 37 | cache files. 38 | 39 | If you need to do unusual things to compile the package, please try 40 | to figure out how `configure' could check whether to do them, and mail 41 | diffs or instructions to the address given in the `README' so they can 42 | be considered for the next release. If you are using the cache, and at 43 | some point `config.cache' contains results you don't want to keep, you 44 | may remove or edit it. 45 | 46 | The file `configure.ac' (or `configure.in') is used to create 47 | `configure' by a program called `autoconf'. You need `configure.ac' if 48 | you want to change it or regenerate `configure' using a newer version 49 | of `autoconf'. 50 | 51 | The simplest way to compile this package is: 52 | 53 | 1. `cd' to the directory containing the package's source code and type 54 | `./configure --enable-debug=yes' to configure the package for your system. 55 | 56 | Running `configure' might take a while. While running, it prints 57 | some messages telling which features it is checking for. 58 | 59 | 2. Type `make' to compile the package. 60 | 61 | 3. Optionally, type `make check' to run any self-tests that come with 62 | the package, generally using the just-built uninstalled binaries. 63 | 64 | 4. Type `make install' to install the programs and any data files and 65 | documentation. When installing into a prefix owned by root, it is 66 | recommended that the package be configured and built as a regular 67 | user, and only the `make install' phase executed with root 68 | privileges. 69 | 70 | 5. Optionally, type `make installcheck' to repeat any self-tests, but 71 | this time using the binaries in their final installed location. 72 | This target does not install anything. Running this target as a 73 | regular user, particularly if the prior `make install' required 74 | root privileges, verifies that the installation completed 75 | correctly. 76 | 77 | 6. You can remove the program binaries and object files from the 78 | source code directory by typing `make clean'. To also remove the 79 | files that `configure' created (so you can compile the package for 80 | a different kind of computer), type `make distclean'. There is 81 | also a `make maintainer-clean' target, but that is intended mainly 82 | for the package's developers. If you use it, you may have to get 83 | all sorts of other programs in order to regenerate files that came 84 | with the distribution. 85 | 86 | 7. Often, you can also type `make uninstall' to remove the installed 87 | files again. In practice, not all packages have tested that 88 | uninstallation works correctly, even though it is required by the 89 | GNU Coding Standards. 90 | 91 | 8. Some packages, particularly those that use Automake, provide `make 92 | distcheck', which can by used by developers to test that all other 93 | targets like `make install' and `make uninstall' work correctly. 94 | This target is generally not run by end users. 95 | 96 | Compilers and Options 97 | ===================== 98 | 99 | Some systems require unusual options for compilation or linking that 100 | the `configure' script does not know about. Run `./configure --help' 101 | for details on some of the pertinent environment variables. 102 | 103 | You can give `configure' initial values for configuration parameters 104 | by setting variables in the command line or in the environment. Here 105 | is an example: 106 | 107 | ./configure CC=c99 CFLAGS=-g LIBS=-lposix 108 | 109 | *Note Defining Variables::, for more details. 110 | 111 | Compiling For Multiple Architectures 112 | ==================================== 113 | 114 | You can compile the package for more than one kind of computer at the 115 | same time, by placing the object files for each architecture in their 116 | own directory. To do this, you can use GNU `make'. `cd' to the 117 | directory where you want the object files and executables to go and run 118 | the `configure' script. `configure' automatically checks for the 119 | source code in the directory that `configure' is in and in `..'. This 120 | is known as a "VPATH" build. 121 | 122 | With a non-GNU `make', it is safer to compile the package for one 123 | architecture at a time in the source code directory. After you have 124 | installed the package for one architecture, use `make distclean' before 125 | reconfiguring for another architecture. 126 | 127 | On MacOS X 10.5 and later systems, you can create libraries and 128 | executables that work on multiple system types--known as "fat" or 129 | "universal" binaries--by specifying multiple `-arch' options to the 130 | compiler but only a single `-arch' option to the preprocessor. Like 131 | this: 132 | 133 | ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ 134 | CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ 135 | CPP="gcc -E" CXXCPP="g++ -E" 136 | 137 | This is not guaranteed to produce working output in all cases, you 138 | may have to build one architecture at a time and combine the results 139 | using the `lipo' tool if you have problems. 140 | 141 | Installation Names 142 | ================== 143 | 144 | By default, `make install' installs the package's commands under 145 | `/usr/local/bin', include files under `/usr/local/include', etc. You 146 | can specify an installation prefix other than `/usr/local' by giving 147 | `configure' the option `--prefix=PREFIX', where PREFIX must be an 148 | absolute file name. 149 | 150 | You can specify separate installation prefixes for 151 | architecture-specific files and architecture-independent files. If you 152 | pass the option `--exec-prefix=PREFIX' to `configure', the package uses 153 | PREFIX as the prefix for installing programs and libraries. 154 | Documentation and other data files still use the regular prefix. 155 | 156 | In addition, if you use an unusual directory layout you can give 157 | options like `--bindir=DIR' to specify different values for particular 158 | kinds of files. Run `configure --help' for a list of the directories 159 | you can set and what kinds of files go in them. In general, the 160 | default for these options is expressed in terms of `${prefix}', so that 161 | specifying just `--prefix' will affect all of the other directory 162 | specifications that were not explicitly provided. 163 | 164 | The most portable way to affect installation locations is to pass the 165 | correct locations to `configure'; however, many packages provide one or 166 | both of the following shortcuts of passing variable assignments to the 167 | `make install' command line to change installation locations without 168 | having to reconfigure or recompile. 169 | 170 | The first method involves providing an override variable for each 171 | affected directory. For example, `make install 172 | prefix=/alternate/directory' will choose an alternate location for all 173 | directory configuration variables that were expressed in terms of 174 | `${prefix}'. Any directories that were specified during `configure', 175 | but not in terms of `${prefix}', must each be overridden at install 176 | time for the entire installation to be relocated. The approach of 177 | makefile variable overrides for each directory variable is required by 178 | the GNU Coding Standards, and ideally causes no recompilation. 179 | However, some platforms have known limitations with the semantics of 180 | shared libraries that end up requiring recompilation when using this 181 | method, particularly noticeable in packages that use GNU Libtool. 182 | 183 | The second method involves providing the `DESTDIR' variable. For 184 | example, `make install DESTDIR=/alternate/directory' will prepend 185 | `/alternate/directory' before all installation names. The approach of 186 | `DESTDIR' overrides is not required by the GNU Coding Standards, and 187 | does not work on platforms that have drive letters. On the other hand, 188 | it does better at avoiding recompilation issues, and works well even 189 | when some directory options were not specified in terms of `${prefix}' 190 | at `configure' time. 191 | 192 | Optional Features 193 | ================= 194 | 195 | If the package supports it, you can cause programs to be installed 196 | with an extra prefix or suffix on their names by giving `configure' the 197 | option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. 198 | 199 | Some packages pay attention to `--enable-FEATURE' options to 200 | `configure', where FEATURE indicates an optional part of the package. 201 | They may also pay attention to `--with-PACKAGE' options, where PACKAGE 202 | is something like `gnu-as' or `x' (for the X Window System). The 203 | `README' should mention any `--enable-' and `--with-' options that the 204 | package recognizes. 205 | 206 | For packages that use the X Window System, `configure' can usually 207 | find the X include and library files automatically, but if it doesn't, 208 | you can use the `configure' options `--x-includes=DIR' and 209 | `--x-libraries=DIR' to specify their locations. 210 | 211 | Some packages offer the ability to configure how verbose the 212 | execution of `make' will be. For these packages, running `./configure 213 | --enable-silent-rules' sets the default to minimal output, which can be 214 | overridden with `make V=1'; while running `./configure 215 | --disable-silent-rules' sets the default to verbose, which can be 216 | overridden with `make V=0'. 217 | 218 | Particular systems 219 | ================== 220 | 221 | On HP-UX, the default C compiler is not ANSI C compatible. If GNU 222 | CC is not installed, it is recommended to use the following options in 223 | order to use an ANSI C compiler: 224 | 225 | ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" 226 | 227 | and if that doesn't work, install pre-built binaries of GCC for HP-UX. 228 | 229 | HP-UX `make' updates targets which have the same time stamps as 230 | their prerequisites, which makes it generally unusable when shipped 231 | generated files such as `configure' are involved. Use GNU `make' 232 | instead. 233 | 234 | On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot 235 | parse its `' header file. The option `-nodtk' can be used as 236 | a workaround. If GNU CC is not installed, it is therefore recommended 237 | to try 238 | 239 | ./configure CC="cc" 240 | 241 | and if that doesn't work, try 242 | 243 | ./configure CC="cc -nodtk" 244 | 245 | On Solaris, don't put `/usr/ucb' early in your `PATH'. This 246 | directory contains several dysfunctional programs; working variants of 247 | these programs are available in `/usr/bin'. So, if you need `/usr/ucb' 248 | in your `PATH', put it _after_ `/usr/bin'. 249 | 250 | On Haiku, software installed for all users goes in `/boot/common', 251 | not `/usr/local'. It is recommended to use the following options: 252 | 253 | ./configure --prefix=/boot/common 254 | 255 | Specifying the System Type 256 | ========================== 257 | 258 | There may be some features `configure' cannot figure out 259 | automatically, but needs to determine by the type of machine the package 260 | will run on. Usually, assuming the package is built to be run on the 261 | _same_ architectures, `configure' can figure that out, but if it prints 262 | a message saying it cannot guess the machine type, give it the 263 | `--build=TYPE' option. TYPE can either be a short name for the system 264 | type, such as `sun4', or a canonical name which has the form: 265 | 266 | CPU-COMPANY-SYSTEM 267 | 268 | where SYSTEM can have one of these forms: 269 | 270 | OS 271 | KERNEL-OS 272 | 273 | See the file `config.sub' for the possible values of each field. If 274 | `config.sub' isn't included in this package, then this package doesn't 275 | need to know the machine type. 276 | 277 | If you are _building_ compiler tools for cross-compiling, you should 278 | use the option `--target=TYPE' to select the type of system they will 279 | produce code for. 280 | 281 | If you want to _use_ a cross compiler, that generates code for a 282 | platform different from the build platform, you should specify the 283 | "host" platform (i.e., that on which the generated programs will 284 | eventually be run) with `--host=TYPE'. 285 | 286 | Sharing Defaults 287 | ================ 288 | 289 | If you want to set default values for `configure' scripts to share, 290 | you can create a site shell script called `config.site' that gives 291 | default values for variables like `CC', `cache_file', and `prefix'. 292 | `configure' looks for `PREFIX/share/config.site' if it exists, then 293 | `PREFIX/etc/config.site' if it exists. Or, you can set the 294 | `CONFIG_SITE' environment variable to the location of the site script. 295 | A warning: not all `configure' scripts look for a site script. 296 | 297 | Defining Variables 298 | ================== 299 | 300 | Variables not defined in a site shell script can be set in the 301 | environment passed to `configure'. However, some packages may run 302 | configure again during the build, and the customized values of these 303 | variables may be lost. In order to avoid this problem, you should set 304 | them in the `configure' command line, using `VAR=value'. For example: 305 | 306 | ./configure CC=/usr/local2/bin/gcc 307 | 308 | causes the specified `gcc' to be used as the C compiler (unless it is 309 | overridden in the site shell script). 310 | 311 | Unfortunately, this technique does not work for `CONFIG_SHELL' due to 312 | an Autoconf limitation. Until the limitation is lifted, you can use 313 | this workaround: 314 | 315 | CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash 316 | 317 | `configure' Invocation 318 | ====================== 319 | 320 | `configure' recognizes the following options to control how it 321 | operates. 322 | 323 | `--help' 324 | `-h' 325 | Print a summary of all of the options to `configure', and exit. 326 | 327 | `--help=short' 328 | `--help=recursive' 329 | Print a summary of the options unique to this package's 330 | `configure', and exit. The `short' variant lists options used 331 | only in the top level, while the `recursive' variant lists options 332 | also present in any nested packages. 333 | 334 | `--version' 335 | `-V' 336 | Print the version of Autoconf used to generate the `configure' 337 | script, and exit. 338 | 339 | `--cache-file=FILE' 340 | Enable the cache: use and save the results of the tests in FILE, 341 | traditionally `config.cache'. FILE defaults to `/dev/null' to 342 | disable caching. 343 | 344 | `--config-cache' 345 | `-C' 346 | Alias for `--cache-file=config.cache'. 347 | 348 | `--quiet' 349 | `--silent' 350 | `-q' 351 | Do not print messages saying which checks are being made. To 352 | suppress all normal output, redirect it to `/dev/null' (any error 353 | messages will still be shown). 354 | 355 | `--srcdir=DIR' 356 | Look for the package's source code in directory DIR. Usually 357 | `configure' can determine that directory automatically. 358 | 359 | `--prefix=DIR' 360 | Use DIR as the installation prefix. *note Installation Names:: 361 | for more details, including other options available for fine-tuning 362 | the installation locations. 363 | 364 | `--no-create' 365 | `-n' 366 | Run the configure checks, but stop before creating any output 367 | files. 368 | 369 | `configure' also accepts some other, not widely useful, options. Run 370 | `configure --help' for more details. 371 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 2.1, February 1999 3 | 4 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | [This is the first released version of the Lesser GPL. It also counts 10 | as the successor of the GNU Library Public License, version 2, hence 11 | the version number 2.1.] 12 | 13 | Preamble 14 | 15 | The licenses for most software are designed to take away your 16 | freedom to share and change it. By contrast, the GNU General Public 17 | Licenses are intended to guarantee your freedom to share and change 18 | free software--to make sure the software is free for all its users. 19 | 20 | This license, the Lesser General Public License, applies to some 21 | specially designated software packages--typically libraries--of the 22 | Free Software Foundation and other authors who decide to use it. You 23 | can use it too, but we suggest you first think carefully about whether 24 | this license or the ordinary General Public License is the better 25 | strategy to use in any particular case, based on the explanations below. 26 | 27 | When we speak of free software, we are referring to freedom of use, 28 | not price. Our General Public Licenses are designed to make sure that 29 | you have the freedom to distribute copies of free software (and charge 30 | for this service if you wish); that you receive source code or can get 31 | it if you want it; that you can change the software and use pieces of 32 | it in new free programs; and that you are informed that you can do 33 | these things. 34 | 35 | To protect your rights, we need to make restrictions that forbid 36 | distributors to deny you these rights or to ask you to surrender these 37 | rights. These restrictions translate to certain responsibilities for 38 | you if you distribute copies of the library or if you modify it. 39 | 40 | For example, if you distribute copies of the library, whether gratis 41 | or for a fee, you must give the recipients all the rights that we gave 42 | you. You must make sure that they, too, receive or can get the source 43 | code. If you link other code with the library, you must provide 44 | complete object files to the recipients, so that they can relink them 45 | with the library after making changes to the library and recompiling 46 | it. And you must show them these terms so they know their rights. 47 | 48 | We protect your rights with a two-step method: (1) we copyright the 49 | library, and (2) we offer you this license, which gives you legal 50 | permission to copy, distribute and/or modify the library. 51 | 52 | To protect each distributor, we want to make it very clear that 53 | there is no warranty for the free library. Also, if the library is 54 | modified by someone else and passed on, the recipients should know 55 | that what they have is not the original version, so that the original 56 | author's reputation will not be affected by problems that might be 57 | introduced by others. 58 | 59 | Finally, software patents pose a constant threat to the existence of 60 | any free program. We wish to make sure that a company cannot 61 | effectively restrict the users of a free program by obtaining a 62 | restrictive license from a patent holder. Therefore, we insist that 63 | any patent license obtained for a version of the library must be 64 | consistent with the full freedom of use specified in this license. 65 | 66 | Most GNU software, including some libraries, is covered by the 67 | ordinary GNU General Public License. This license, the GNU Lesser 68 | General Public License, applies to certain designated libraries, and 69 | is quite different from the ordinary General Public License. We use 70 | this license for certain libraries in order to permit linking those 71 | libraries into non-free programs. 72 | 73 | When a program is linked with a library, whether statically or using 74 | a shared library, the combination of the two is legally speaking a 75 | combined work, a derivative of the original library. The ordinary 76 | General Public License therefore permits such linking only if the 77 | entire combination fits its criteria of freedom. The Lesser General 78 | Public License permits more lax criteria for linking other code with 79 | the library. 80 | 81 | We call this license the "Lesser" General Public License because it 82 | does Less to protect the user's freedom than the ordinary General 83 | Public License. It also provides other free software developers Less 84 | of an advantage over competing non-free programs. These disadvantages 85 | are the reason we use the ordinary General Public License for many 86 | libraries. However, the Lesser license provides advantages in certain 87 | special circumstances. 88 | 89 | For example, on rare occasions, there may be a special need to 90 | encourage the widest possible use of a certain library, so that it becomes 91 | a de-facto standard. To achieve this, non-free programs must be 92 | allowed to use the library. A more frequent case is that a free 93 | library does the same job as widely used non-free libraries. In this 94 | case, there is little to gain by limiting the free library to free 95 | software only, so we use the Lesser General Public License. 96 | 97 | In other cases, permission to use a particular library in non-free 98 | programs enables a greater number of people to use a large body of 99 | free software. For example, permission to use the GNU C Library in 100 | non-free programs enables many more people to use the whole GNU 101 | operating system, as well as its variant, the GNU/Linux operating 102 | system. 103 | 104 | Although the Lesser General Public License is Less protective of the 105 | users' freedom, it does ensure that the user of a program that is 106 | linked with the Library has the freedom and the wherewithal to run 107 | that program using a modified version of the Library. 108 | 109 | The precise terms and conditions for copying, distribution and 110 | modification follow. Pay close attention to the difference between a 111 | "work based on the library" and a "work that uses the library". The 112 | former contains code derived from the library, whereas the latter must 113 | be combined with the library in order to run. 114 | 115 | GNU LESSER GENERAL PUBLIC LICENSE 116 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 117 | 118 | 0. This License Agreement applies to any software library or other 119 | program which contains a notice placed by the copyright holder or 120 | other authorized party saying it may be distributed under the terms of 121 | this Lesser General Public License (also called "this License"). 122 | Each licensee is addressed as "you". 123 | 124 | A "library" means a collection of software functions and/or data 125 | prepared so as to be conveniently linked with application programs 126 | (which use some of those functions and data) to form executables. 127 | 128 | The "Library", below, refers to any such software library or work 129 | which has been distributed under these terms. A "work based on the 130 | Library" means either the Library or any derivative work under 131 | copyright law: that is to say, a work containing the Library or a 132 | portion of it, either verbatim or with modifications and/or translated 133 | straightforwardly into another language. (Hereinafter, translation is 134 | included without limitation in the term "modification".) 135 | 136 | "Source code" for a work means the preferred form of the work for 137 | making modifications to it. For a library, complete source code means 138 | all the source code for all modules it contains, plus any associated 139 | interface definition files, plus the scripts used to control compilation 140 | and installation of the library. 141 | 142 | Activities other than copying, distribution and modification are not 143 | covered by this License; they are outside its scope. The act of 144 | running a program using the Library is not restricted, and output from 145 | such a program is covered only if its contents constitute a work based 146 | on the Library (independent of the use of the Library in a tool for 147 | writing it). Whether that is true depends on what the Library does 148 | and what the program that uses the Library does. 149 | 150 | 1. You may copy and distribute verbatim copies of the Library's 151 | complete source code as you receive it, in any medium, provided that 152 | you conspicuously and appropriately publish on each copy an 153 | appropriate copyright notice and disclaimer of warranty; keep intact 154 | all the notices that refer to this License and to the absence of any 155 | warranty; and distribute a copy of this License along with the 156 | Library. 157 | 158 | You may charge a fee for the physical act of transferring a copy, 159 | and you may at your option offer warranty protection in exchange for a 160 | fee. 161 | 162 | 2. You may modify your copy or copies of the Library or any portion 163 | of it, thus forming a work based on the Library, and copy and 164 | distribute such modifications or work under the terms of Section 1 165 | above, provided that you also meet all of these conditions: 166 | 167 | a) The modified work must itself be a software library. 168 | 169 | b) You must cause the files modified to carry prominent notices 170 | stating that you changed the files and the date of any change. 171 | 172 | c) You must cause the whole of the work to be licensed at no 173 | charge to all third parties under the terms of this License. 174 | 175 | d) If a facility in the modified Library refers to a function or a 176 | table of data to be supplied by an application program that uses 177 | the facility, other than as an argument passed when the facility 178 | is invoked, then you must make a good faith effort to ensure that, 179 | in the event an application does not supply such function or 180 | table, the facility still operates, and performs whatever part of 181 | its purpose remains meaningful. 182 | 183 | (For example, a function in a library to compute square roots has 184 | a purpose that is entirely well-defined independent of the 185 | application. Therefore, Subsection 2d requires that any 186 | application-supplied function or table used by this function must 187 | be optional: if the application does not supply it, the square 188 | root function must still compute square roots.) 189 | 190 | These requirements apply to the modified work as a whole. If 191 | identifiable sections of that work are not derived from the Library, 192 | and can be reasonably considered independent and separate works in 193 | themselves, then this License, and its terms, do not apply to those 194 | sections when you distribute them as separate works. But when you 195 | distribute the same sections as part of a whole which is a work based 196 | on the Library, the distribution of the whole must be on the terms of 197 | this License, whose permissions for other licensees extend to the 198 | entire whole, and thus to each and every part regardless of who wrote 199 | it. 200 | 201 | Thus, it is not the intent of this section to claim rights or contest 202 | your rights to work written entirely by you; rather, the intent is to 203 | exercise the right to control the distribution of derivative or 204 | collective works based on the Library. 205 | 206 | In addition, mere aggregation of another work not based on the Library 207 | with the Library (or with a work based on the Library) on a volume of 208 | a storage or distribution medium does not bring the other work under 209 | the scope of this License. 210 | 211 | 3. You may opt to apply the terms of the ordinary GNU General Public 212 | License instead of this License to a given copy of the Library. To do 213 | this, you must alter all the notices that refer to this License, so 214 | that they refer to the ordinary GNU General Public License, version 2, 215 | instead of to this License. (If a newer version than version 2 of the 216 | ordinary GNU General Public License has appeared, then you can specify 217 | that version instead if you wish.) Do not make any other change in 218 | these notices. 219 | 220 | Once this change is made in a given copy, it is irreversible for 221 | that copy, so the ordinary GNU General Public License applies to all 222 | subsequent copies and derivative works made from that copy. 223 | 224 | This option is useful when you wish to copy part of the code of 225 | the Library into a program that is not a library. 226 | 227 | 4. You may copy and distribute the Library (or a portion or 228 | derivative of it, under Section 2) in object code or executable form 229 | under the terms of Sections 1 and 2 above provided that you accompany 230 | it with the complete corresponding machine-readable source code, which 231 | must be distributed under the terms of Sections 1 and 2 above on a 232 | medium customarily used for software interchange. 233 | 234 | If distribution of object code is made by offering access to copy 235 | from a designated place, then offering equivalent access to copy the 236 | source code from the same place satisfies the requirement to 237 | distribute the source code, even though third parties are not 238 | compelled to copy the source along with the object code. 239 | 240 | 5. A program that contains no derivative of any portion of the 241 | Library, but is designed to work with the Library by being compiled or 242 | linked with it, is called a "work that uses the Library". Such a 243 | work, in isolation, is not a derivative work of the Library, and 244 | therefore falls outside the scope of this License. 245 | 246 | However, linking a "work that uses the Library" with the Library 247 | creates an executable that is a derivative of the Library (because it 248 | contains portions of the Library), rather than a "work that uses the 249 | library". The executable is therefore covered by this License. 250 | Section 6 states terms for distribution of such executables. 251 | 252 | When a "work that uses the Library" uses material from a header file 253 | that is part of the Library, the object code for the work may be a 254 | derivative work of the Library even though the source code is not. 255 | Whether this is true is especially significant if the work can be 256 | linked without the Library, or if the work is itself a library. The 257 | threshold for this to be true is not precisely defined by law. 258 | 259 | If such an object file uses only numerical parameters, data 260 | structure layouts and accessors, and small macros and small inline 261 | functions (ten lines or less in length), then the use of the object 262 | file is unrestricted, regardless of whether it is legally a derivative 263 | work. (Executables containing this object code plus portions of the 264 | Library will still fall under Section 6.) 265 | 266 | Otherwise, if the work is a derivative of the Library, you may 267 | distribute the object code for the work under the terms of Section 6. 268 | Any executables containing that work also fall under Section 6, 269 | whether or not they are linked directly with the Library itself. 270 | 271 | 6. As an exception to the Sections above, you may also combine or 272 | link a "work that uses the Library" with the Library to produce a 273 | work containing portions of the Library, and distribute that work 274 | under terms of your choice, provided that the terms permit 275 | modification of the work for the customer's own use and reverse 276 | engineering for debugging such modifications. 277 | 278 | You must give prominent notice with each copy of the work that the 279 | Library is used in it and that the Library and its use are covered by 280 | this License. You must supply a copy of this License. If the work 281 | during execution displays copyright notices, you must include the 282 | copyright notice for the Library among them, as well as a reference 283 | directing the user to the copy of this License. Also, you must do one 284 | of these things: 285 | 286 | a) Accompany the work with the complete corresponding 287 | machine-readable source code for the Library including whatever 288 | changes were used in the work (which must be distributed under 289 | Sections 1 and 2 above); and, if the work is an executable linked 290 | with the Library, with the complete machine-readable "work that 291 | uses the Library", as object code and/or source code, so that the 292 | user can modify the Library and then relink to produce a modified 293 | executable containing the modified Library. (It is understood 294 | that the user who changes the contents of definitions files in the 295 | Library will not necessarily be able to recompile the application 296 | to use the modified definitions.) 297 | 298 | b) Use a suitable shared library mechanism for linking with the 299 | Library. A suitable mechanism is one that (1) uses at run time a 300 | copy of the library already present on the user's computer system, 301 | rather than copying library functions into the executable, and (2) 302 | will operate properly with a modified version of the library, if 303 | the user installs one, as long as the modified version is 304 | interface-compatible with the version that the work was made with. 305 | 306 | c) Accompany the work with a written offer, valid for at 307 | least three years, to give the same user the materials 308 | specified in Subsection 6a, above, for a charge no more 309 | than the cost of performing this distribution. 310 | 311 | d) If distribution of the work is made by offering access to copy 312 | from a designated place, offer equivalent access to copy the above 313 | specified materials from the same place. 314 | 315 | e) Verify that the user has already received a copy of these 316 | materials or that you have already sent this user a copy. 317 | 318 | For an executable, the required form of the "work that uses the 319 | Library" must include any data and utility programs needed for 320 | reproducing the executable from it. However, as a special exception, 321 | the materials to be distributed need not include anything that is 322 | normally distributed (in either source or binary form) with the major 323 | components (compiler, kernel, and so on) of the operating system on 324 | which the executable runs, unless that component itself accompanies 325 | the executable. 326 | 327 | It may happen that this requirement contradicts the license 328 | restrictions of other proprietary libraries that do not normally 329 | accompany the operating system. Such a contradiction means you cannot 330 | use both them and the Library together in an executable that you 331 | distribute. 332 | 333 | 7. You may place library facilities that are a work based on the 334 | Library side-by-side in a single library together with other library 335 | facilities not covered by this License, and distribute such a combined 336 | library, provided that the separate distribution of the work based on 337 | the Library and of the other library facilities is otherwise 338 | permitted, and provided that you do these two things: 339 | 340 | a) Accompany the combined library with a copy of the same work 341 | based on the Library, uncombined with any other library 342 | facilities. This must be distributed under the terms of the 343 | Sections above. 344 | 345 | b) Give prominent notice with the combined library of the fact 346 | that part of it is a work based on the Library, and explaining 347 | where to find the accompanying uncombined form of the same work. 348 | 349 | 8. You may not copy, modify, sublicense, link with, or distribute 350 | the Library except as expressly provided under this License. Any 351 | attempt otherwise to copy, modify, sublicense, link with, or 352 | distribute the Library is void, and will automatically terminate your 353 | rights under this License. However, parties who have received copies, 354 | or rights, from you under this License will not have their licenses 355 | terminated so long as such parties remain in full compliance. 356 | 357 | 9. You are not required to accept this License, since you have not 358 | signed it. However, nothing else grants you permission to modify or 359 | distribute the Library or its derivative works. These actions are 360 | prohibited by law if you do not accept this License. Therefore, by 361 | modifying or distributing the Library (or any work based on the 362 | Library), you indicate your acceptance of this License to do so, and 363 | all its terms and conditions for copying, distributing or modifying 364 | the Library or works based on it. 365 | 366 | 10. Each time you redistribute the Library (or any work based on the 367 | Library), the recipient automatically receives a license from the 368 | original licensor to copy, distribute, link with or modify the Library 369 | subject to these terms and conditions. You may not impose any further 370 | restrictions on the recipients' exercise of the rights granted herein. 371 | You are not responsible for enforcing compliance by third parties with 372 | this License. 373 | 374 | 11. If, as a consequence of a court judgment or allegation of patent 375 | infringement or for any other reason (not limited to patent issues), 376 | conditions are imposed on you (whether by court order, agreement or 377 | otherwise) that contradict the conditions of this License, they do not 378 | excuse you from the conditions of this License. If you cannot 379 | distribute so as to satisfy simultaneously your obligations under this 380 | License and any other pertinent obligations, then as a consequence you 381 | may not distribute the Library at all. For example, if a patent 382 | license would not permit royalty-free redistribution of the Library by 383 | all those who receive copies directly or indirectly through you, then 384 | the only way you could satisfy both it and this License would be to 385 | refrain entirely from distribution of the Library. 386 | 387 | If any portion of this section is held invalid or unenforceable under any 388 | particular circumstance, the balance of the section is intended to apply, 389 | and the section as a whole is intended to apply in other circumstances. 390 | 391 | It is not the purpose of this section to induce you to infringe any 392 | patents or other property right claims or to contest validity of any 393 | such claims; this section has the sole purpose of protecting the 394 | integrity of the free software distribution system which is 395 | implemented by public license practices. Many people have made 396 | generous contributions to the wide range of software distributed 397 | through that system in reliance on consistent application of that 398 | system; it is up to the author/donor to decide if he or she is willing 399 | to distribute software through any other system and a licensee cannot 400 | impose that choice. 401 | 402 | This section is intended to make thoroughly clear what is believed to 403 | be a consequence of the rest of this License. 404 | 405 | 12. If the distribution and/or use of the Library is restricted in 406 | certain countries either by patents or by copyrighted interfaces, the 407 | original copyright holder who places the Library under this License may add 408 | an explicit geographical distribution limitation excluding those countries, 409 | so that distribution is permitted only in or among countries not thus 410 | excluded. In such case, this License incorporates the limitation as if 411 | written in the body of this License. 412 | 413 | 13. The Free Software Foundation may publish revised and/or new 414 | versions of the Lesser General Public License from time to time. 415 | Such new versions will be similar in spirit to the present version, 416 | but may differ in detail to address new problems or concerns. 417 | 418 | Each version is given a distinguishing version number. If the Library 419 | specifies a version number of this License which applies to it and 420 | "any later version", you have the option of following the terms and 421 | conditions either of that version or of any later version published by 422 | the Free Software Foundation. If the Library does not specify a 423 | license version number, you may choose any version ever published by 424 | the Free Software Foundation. 425 | 426 | 14. If you wish to incorporate parts of the Library into other free 427 | programs whose distribution conditions are incompatible with these, 428 | write to the author to ask for permission. For software which is 429 | copyrighted by the Free Software Foundation, write to the Free 430 | Software Foundation; we sometimes make exceptions for this. Our 431 | decision will be guided by the two goals of preserving the free status 432 | of all derivatives of our free software and of promoting the sharing 433 | and reuse of software generally. 434 | 435 | NO WARRANTY 436 | 437 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 438 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 439 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 440 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 441 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 442 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 443 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 444 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 445 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 446 | 447 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 448 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 449 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 450 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 451 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 452 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 453 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 454 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 455 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 456 | DAMAGES. 457 | 458 | END OF TERMS AND CONDITIONS 459 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | AUTOMAKE_OPTIONS = foreign 2 | SUBDIRS = src test 3 | 4 | # Nonstandard package files for distribution 5 | EXTRA_DIST = \ 6 | HOWTO.txt \ 7 | TODO.txt \ 8 | LICENSE \ 9 | preamble \ 10 | test/generate_ipv4.py \ 11 | test/raw-ips 12 | 13 | ACLOCAL_AMFLAGS = -I m4 14 | 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | libFNR - A reference implementation library for FNR encryption scheme. 3 | 4 | FNR represents "Flexible Naor and Reingold" 5 | 6 | FNR is a small domain block cipher for encrypting 7 | objects ( < 128 bits ) like IPv4, MAC, Credit Card numbers, Time Stamps etc. 8 | 9 | ## INSTALL 10 | 11 | NOTE : openssl latest version (> openssl-1.0.1e) needs to be installed 12 | 13 | ```shell 14 | # The bootstrap.sh step is only ncessary if you are building from a 15 | # git clone; it is not necessary if you are building from a libfnr 16 | # tarball. 17 | $ bootstrap.sh 18 | 19 | $ ./configure --enable-debug=yes 20 | $ make 21 | ``` 22 | 23 | ## RUN 24 | 25 | ```shell 26 | $ cd test 27 | $ ./ipv4test -p password -t tweak -f raw-ips 28 | ``` 29 | 30 | IMPORTANT: This is an *experimental* cipher, not for production yet. 31 | 32 | Motivation and Applications of this scheme could be found at 33 | http://cisco.github.io/libfnr/ 34 | 35 | Java extensions for this library could be found at 36 | https://github.com/cisco/jfnr 37 | 38 | Details of the Specification could be found in 39 | doc/Spec directory 40 | 41 | Report bugs to 42 | 43 | FNR is designed by 44 | * Sashank Dara (sadara@cisco.com), 45 | * Scott Fluhrer (sfluhrer@cisco.com) 46 | 47 | Copyright (C) 2014-2015, Cisco Systems, Inc. 48 | -------------------------------------------------------------------------------- /TODO.txt: -------------------------------------------------------------------------------- 1 | Fix Bugs, if any in both core code and test code 2 | Good unit test coverage 3 | Support more Data formats like MAC Addresses, IPv6, SSNs, URLs, Filepaths etc. 4 | Support more languages, platforms like Java, Javascript, C++ etc. 5 | 6 | -------------------------------------------------------------------------------- /bootstrap.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | if test ! -d m4; then 4 | mkdir m4 5 | fi 6 | 7 | autoreconf -ivf 8 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # 3 | # Copyright (c) 2014 Cisco Systems, Inc. 4 | # 5 | 6 | AC_PREREQ([2.59]) 7 | AC_INIT([fnr], [1.0.0], [libfnr-dev@external.cisco.com]) 8 | AM_INIT_AUTOMAKE([1.11 dist-bzip2 foreign -Wall -Werror]) 9 | AC_CONFIG_SRCDIR([src/fnr.c]) 10 | AC_CONFIG_HEADERS([config.h]) 11 | 12 | AC_CONFIG_MACRO_DIR([m4]) 13 | 14 | m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) 15 | 16 | # Checks for programs. 17 | :${CFLAGS=""} 18 | AC_PROG_CC 19 | AM_PROG_CC_C_O 20 | 21 | # This did not exist pre AM 1.11.x (where x is somewhere >0 and <3), 22 | # but it is necessary in AM 1.12.x. 23 | m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) 24 | 25 | # SSL options 26 | AC_ARG_WITH([libssl], AC_HELP_STRING([--with-libssl=DIR], [use libssl in DIR]), 27 | [], [with_libssl=yes]) 28 | AS_CASE([$with_libssl], 29 | [yes], [], 30 | [no], [AC_MSG_NOTICE([libfnr requires libssl -- specifying --without-libssl is disallowed]) 31 | AC_MSG_ERROR([Cannot continue])], 32 | [AS_IF([test ! -d "$with_libssl"], 33 | [AC_MSG_NOTICE([Supplied SSL directory $with_libssl does not exist]) 34 | AC_MSG_ERROR([Cannot continue])]) 35 | AS_IF([test ! -d "$with_libssl/include"], 36 | [AC_MSG_NOTICE([Supplied SSL directory $with_libssl/include does not exist]) 37 | AC_MSG_ERROR([Cannot continue])]) 38 | CPPFLAGS="$CPPFLAGS -I$with_libssl/include" 39 | CXXCPPFLAGS="$CXXCPPFLAGS -I$with_libssl/include" 40 | 41 | AS_IF([test -d "$with_libssl/lib"], [LDFLAGS="-L$with_libssl/lib"], 42 | [AS_IF([test -d "$with_libssl/lib64"], 43 | [LDFLAGS="-L$with_libssl/lib64"], 44 | [AC_MSG_NOTICE([Cannot find $with_libssl/lib or $with_libssl/lib64]) 45 | AC_MSG_ERROR([Cannot continute])]) 46 | ]) 47 | ]) 48 | 49 | # Checks for header files. 50 | AC_CHECK_HEADERS([string.h]) 51 | AC_CHECK_HEADER([openssl/aes.h], [], 52 | [AC_MSG_NOTICE([Cannot find openssl/aes.h]) 53 | AC_MSG_ERROR([Cannot continue])]) 54 | 55 | # Checks for typedefs, structures, and compiler characteristics. 56 | 57 | # Checks for library functions. 58 | AC_FUNC_MALLOC 59 | AC_CHECK_FUNCS([memset]) 60 | AC_CHECK_LIB([crypto], [AES_set_encrypt_key], [], 61 | [AC_MSG_NOTICE([Cannot find libcrypto]) 62 | AC_MSG_ERROR([Cannot continue])]) 63 | AC_CHECK_LIB([ssl], [SSL_set_msg_callback], [], 64 | [AC_MSG_NOTICE([Cannot find libssl]) 65 | AC_MSG_ERROR([Cannot continue])]) 66 | 67 | LT_INIT 68 | 69 | AC_CONFIG_FILES([Makefile 70 | src/Makefile 71 | test/Makefile]) 72 | 73 | AC_ARG_ENABLE(debug, 74 | AS_HELP_STRING([--enable-debug], [enable debugging, default: no]), 75 | [case "${enableval}" in 76 | yes) debug=true ;; 77 | no) debug=false ;; 78 | *) AC_MSG_ERROR([bad value ${enableval} for --enable-debug]) ;; 79 | esac], [debug=false]) 80 | AM_CONDITIONAL(DEBUG, test x"$debug" = x"true") 81 | 82 | AC_OUTPUT 83 | 84 | -------------------------------------------------------------------------------- /doc/spec: -------------------------------------------------------------------------------- 1 | Please check the below link for latest version of the specification 2 | http://eprint.iacr.org/2014/421 3 | 4 | -------------------------------------------------------------------------------- /preamble: -------------------------------------------------------------------------------- 1 | /* 2 | * libFNR - A reference implementation library for FNR encryption mode. 3 | * 4 | * FNR represents "Flexible Naor and Reingold" mode 5 | * 6 | * FNR is a small domain block cipher to encrypt small domain 7 | * objects ( < 128 bits ) like IPv4, MAC, Credit Card numbers etc. 8 | * 9 | * FNR is designed by Sashank Dara (sadara@cisco.com), Scott Fluhrer (sfluhrer@cisco.com) 10 | * 11 | * Copyright (C) 2014-2015, Cisco Systems, Inc. 12 | * 13 | * This library is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Lesser General Public 15 | * License as published by the Free Software Foundation; either 16 | * version 2.1 of the License, or (at your option) any later version. 17 | * 18 | * This library is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 | * Lesser General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU Lesser General Public 24 | * License along with this library; if not, write to the Free Software 25 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 26 | * 27 | **/ 28 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2014 Cisco Systems, Inc. 2 | 3 | lib_LTLIBRARIES = libfnr.la 4 | 5 | include_HEADERS = fnr.h 6 | libfnr_la_SOURCES = fnr.c $(include_HEADERS) 7 | libfnr_la_LDFLAGS = -version-info 1:0:0 8 | libfnr_la_LIBADD = $(LIBSSL) 9 | 10 | if DEBUG 11 | AM_CFLAGS = -g3 -O0 12 | else 13 | AM_CFLAGS = -O3 14 | endif 15 | -------------------------------------------------------------------------------- /src/fnr.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libFNR - A reference implementation library for FNR encryption scheme. 3 | * 4 | * FNR represents "Flexible Naor and Reingold" 5 | 6 | * FNR is a small domain block cipher to encrypt small domain 7 | * objects ( < 128 bits ) like IPv4, MAC, Credit Card numbers etc. 8 | 9 | * FNR is designed by Sashank Dara (sadara@cisco.com), Scott Fluhrer (sfluhrer@cisco.com) 10 | * 11 | * fnr.c is written by Scott Fluhrer 12 | * 13 | * Copyright (C) 2014 , Cisco Systems Inc. 14 | * 15 | * This library is free software; you can redistribute it and/or 16 | * modify it under the terms of the GNU Lesser General Public 17 | * License as published by the Free Software Foundation; either 18 | * version 2.1 of the License, or (at your option) any later version. 19 | * 20 | * This library is distributed in the hope that it will be useful, 21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23 | * Lesser General Public License for more details. 24 | * 25 | * You should have received a copy of the GNU Lesser General Public 26 | * License along with this library; if not, write to the Free Software 27 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 28 | * 29 | **/ 30 | #include 31 | #include 32 | #include 33 | #include "fnr.h" 34 | #include "openssl/conf.h" 35 | #include "openssl/aes.h" 36 | #include "openssl/evp.h" 37 | #include "openssl/err.h" 38 | 39 | #define N_ROUND 7 /* Number of Luby-Rackoff rounds we use */ 40 | /* Needs to be odd */ 41 | #define BLOCKSIZE 16 /* AES has 16 bytes blocks. This is here more for */ 42 | /* documentation, and not so much in case we change AES */ 43 | typedef unsigned char element ; /* Internally, the PWIP treat vectors as */ 44 | #define BITS_PER_ELEMENT 8 /* groups of 8 bit elements. A more optimized */ 45 | /* version could use larger elements */ 46 | #define ELEMENTS_PER_ROW(N) (((unsigned)N + BITS_PER_ELEMENT - 1) / BITS_PER_ELEMENT) 47 | 48 | #define TWEAK_MARKER 0xff /* AES encryptions for the purpose of summarizing */ 49 | /* a tweak will have 0xff in the last byte */ 50 | #define RND_MARKER 0xc0 /* AES encryptions for the purpose of selecting a */ 51 | /* PWIP will have 0xc0 in the last byte */ 52 | /* AES encryptions done during encryption/decryption will have one of the */ 53 | /* top two bits of the last byte be clear */ 54 | /* This means that the three ways we invoke AES never collide, and so */ 55 | /* they can safely share the same key */ 56 | 57 | #define SWAP 0 58 | #define XOR 1 59 | /* 60 | * This is the structure we use to store an expand key. We also store the 61 | * arrays used to store the PWIP/invPWIP operations immediately after this 62 | * structure (in the same malloc block) 63 | */ 64 | struct fnr_expanded_key_st { 65 | unsigned full_bytes; /* Number of bytes that makes up the block, not */ 66 | /* counting the last (even if the last is a full byte) */ 67 | unsigned char final_mask; /* Which bits of the last byte are part of the */ 68 | /* block */ 69 | unsigned full_elements; /* Number of elements that makes up the block, not */ 70 | /* counting the last (even if the last is full) */ 71 | element final_element_mask; /* Which bits of the last element are part of the */ 72 | /* block */ 73 | 74 | unsigned num_bits; /* Number of bits within the block */ 75 | size_t size; /* Total size allocated for this structure */ 76 | AES_KEY expanded_aes_key; /* The expanded AES key */ 77 | // unsigned char *aes_key = "01234567890123456"; /* user provided key */ 78 | unsigned char *aes_key ; /* user provided key */ 79 | element *green; /* Pointer to the inverse PWIP structure. It's */ 80 | /* actually allocated after this structure */ 81 | element red[1]; /* The array used for the forward PWIP structure */ 82 | }; 83 | 84 | /* 85 | * The encrypt method of AES 86 | * 87 | */ 88 | static int encrypt(unsigned char *plaintext,unsigned int plaintext_len, 89 | unsigned char *ciphertext , const unsigned char *key) 90 | { 91 | EVP_CIPHER_CTX *ctx; 92 | 93 | int len; 94 | 95 | int ciphertext_len; 96 | 97 | /* Create and initialise the context */ 98 | if (!(ctx = EVP_CIPHER_CTX_new())) FNR_handle_errors(); 99 | 100 | /* Initialise the encryption operation. */ 101 | if (1 != EVP_EncryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, key, NULL)) 102 | FNR_handle_errors(); 103 | 104 | /* Provide the message to be encrypted, and obtain the encrypted output. 105 | * EVP_EncryptUpdate can be called multiple times if necessary 106 | */ 107 | if (1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len)) 108 | FNR_handle_errors(); 109 | ciphertext_len = len; 110 | 111 | /* Finalise the encryption. Further ciphertext bytes may be written at 112 | * this stage. 113 | */ 114 | if (1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) FNR_handle_errors(); 115 | ciphertext_len += len; 116 | 117 | /* Clean up */ 118 | EVP_CIPHER_CTX_free(ctx); 119 | 120 | return ciphertext_len; 121 | } 122 | 123 | /* 124 | The source code for clearing sensitive information is as recommended by 125 | crypto coding guide lines 126 | https://cryptocoding.net/index.php/Coding_rules#Clean_memory_of_secret_data 127 | */ 128 | void FNR_burn( void *v, size_t n ) 129 | { 130 | volatile unsigned char *p = ( volatile unsigned char * )v; 131 | while( n-- ) *p++ = 0; 132 | } 133 | 134 | void FNR_handle_errors(void) 135 | { 136 | ERR_print_errors_fp(stderr); 137 | abort(); 138 | } 139 | /* 140 | * When we select a PWIP matrix, we use a stream of bits to do our selection. 141 | * This is the structure we use to generate those bits. 142 | * This stream of bits needs to be unpredictable and uniformly distributed 143 | * if you don't know the key, and determanistic based on the key and the block 144 | * size. 145 | * 146 | * We stir in the block size in case someone uses the same key for two 147 | * different block sizes; that ensures that the PWIPs generated will be 148 | * unrelated. 149 | * 150 | * This stream is just AES in counter mode. 151 | */ 152 | struct pwip_stream { 153 | fnr_expanded_key *key; 154 | size_t num_bits; /* The cipher block size */ 155 | unsigned count; /* Which block we are currently at */ 156 | unsigned index; /* Which byte in buffer are current at */ 157 | unsigned bit_count; /* Which bit in buffer we are currently at */ 158 | unsigned char buffer[BLOCKSIZE]; 159 | }; 160 | 161 | /* To ensure round function is different for each round */ 162 | static const unsigned char round_const[7] = { 0x00, 0x03, 0x0c, 0x0f, 0x30, 0x33, 0x3c }; 163 | 164 | static void pwip(const fnr_expanded_key *key, const element *m, const void *in, void *out); 165 | 166 | /* 167 | * This returns the next bit from the stream generator 168 | */ 169 | static int next_bit(struct pwip_stream *ctx) { 170 | if (ctx->index == BLOCKSIZE) { 171 | /* We ran out of bits from the previous block; generate a new one */ 172 | unsigned char block[BLOCKSIZE] = { 0 }; 173 | unsigned count = ctx->count++; 174 | block[0] = (count ) & 0xff; /* block[0-3] will be the index */ 175 | block[1] = (count >> 8) & 0xff; 176 | block[2] = (count >> 16) & 0xff; 177 | block[3] = (count >> 24) & 0xff; 178 | block[BLOCKSIZE-2] = ctx->num_bits; /* Stir in the block size (so */ 179 | /* that the same key will generate different PWIPs for different */ 180 | /* block sizes) */ 181 | block[BLOCKSIZE-1] = RND_MARKER; /* We set the last byte to this */ 182 | /* value so that we can know that this AES function evaluation */ 183 | /* will be distinct from either the AES evaluations we do during */ 184 | /* tweak expansion, or during the LR rounds */ 185 | 186 | //encrypt(block,4,ctx->buffer, ctx->key->aes_key); 187 | AES_encrypt(block, ctx->buffer, &ctx->key->expanded_aes_key); 188 | 189 | ctx->index = 0; ctx->bit_count = 0; 190 | } 191 | 192 | /* Get the next bit from the stream */ 193 | int bit = (ctx->buffer[ ctx->index ] >> ctx->bit_count) & 0x01; 194 | 195 | /* Step to the next bit */ 196 | ctx->bit_count++; 197 | if (ctx->bit_count == 8) { 198 | ctx->index++; 199 | ctx->bit_count = 0; 200 | } 201 | 202 | /* Return the bit the we retrieved */ 203 | return bit; 204 | } 205 | 206 | /* Generate 'n' bits; return them as an int */ 207 | static unsigned next_bits(struct pwip_stream *ctx, int n) { 208 | unsigned result = 0; 209 | int i; 210 | for (i=0; ia + 1); 278 | int b_row = elements_per_row * (sub->b + 1); 279 | int i; 280 | 281 | switch (sub->type) { 282 | case SWAP: 283 | for (i=0; i 0) { 348 | SET(SWAP, i, i+first_nonzero); 349 | bits[first_nonzero] = 0; 350 | } 351 | 352 | /* 353 | * Here in Guassian elimination, we would typically multiply row i with 354 | * the inverse of the value in column i, in order to make the value on 355 | * the diagonal 1. However, we're in GF(2); it's already 1, and so we 356 | * can skip that step 357 | */ 358 | 359 | /* 360 | * Go through the later rows; for any row that had a 1 bit, cancel it 361 | * out (by adding row i that to that row) 362 | */ 363 | for (j=1; j0; i--) { 420 | multiply_gen_matrix( n, A, &array[i-1] ); 421 | } 422 | 423 | /* 424 | * Now we need to compute the inverse to that matrix. We could do Yet 425 | * Another Gaussian elimination to invert it; however there's a simpler 426 | * approach. We note that: 427 | * - All the gen_matrices are self-inverses; that is, they all have 428 | * A * A = I, or in other words, A = A^-1 429 | * - Matrix multiplication has this identity (A * B)^-1 = B^-1 * A^-1 430 | * Hence, if A, B, ... Z are all gen_matrices, we have: 431 | * (A * B * ... * Z)^1 = Z^-1 * ... * B^-1 * A^-1 = Z * ... * B * A 432 | * Or, by multiplying them in the other direction, we get the inverse 433 | * Ain't that cool! 434 | */ 435 | for (i=0; i 8) bits_this_time = 8; 449 | A[i/8] = next_bits(stream, bits_this_time); 450 | } 451 | 452 | /* 453 | * Now it is time to add the corresponding vector to the inverse transform. 454 | * One straightforward approach would be to modify the inverse transform so 455 | * that we add the constant to the value we're transforming (rather than 456 | * the output); so in the forward direction we compute PWIP(V) = M*V + C, 457 | * and in the reverse direction, we compute InvPWIP(V) = InvM*(V + C) 458 | * (why InvM*(V+C) and not InvM*(V-C)? Remember, we're working on vectors 459 | * over GF(2), and so + and - are the same operation). 460 | * That would work fine; however I'd prefer to reuse the same code in both 461 | * directions, and so we compute InvC = InvM * C, and hence in the reverse 462 | * direction, we compute InvPWIP(V) = InvM*V + InvC 463 | */ 464 | /* Set the constant vector assigned to the B operation to 0 */ 465 | FNR_burn( &B[0], elements_per_row * sizeof(element) ); 466 | 467 | /* 468 | * Now, take the constant vector assigned to A (which is at the beginning 469 | * of the A array; hence A is a pointer to it), and send it through the B 470 | * operation (which computes InvM * A + 0; the 0 is because we just set the 471 | * constant vector assigned to B to 0), and place that result back where 472 | * the constant vector assigned to B, which is at the beginning of B 473 | */ 474 | pwip(stream->key, B, A, B); 475 | 476 | /* 477 | * Here, A and B represent uniformly distributed affine functions 478 | * (if next_bit() generates independent and uniformly distributed bits) 479 | * which are inverses of each other 480 | */ 481 | 482 | return 1; 483 | } 484 | 485 | /* 486 | * This takes an AES key (and a block size), and expands it, setting all the 487 | * internal parameters (and the PWIP matrices, which is most of the work) 488 | */ 489 | fnr_expanded_key *FNR_expand_key(const void *aes_key, unsigned int aes_key_size, 490 | size_t num_bits) { 491 | if (num_bits < 1 || num_bits > 128) { 492 | /* Parameter out of range */ 493 | return NULL; 494 | } 495 | 496 | /* 497 | * Compute how much size the expanded key will take up; that's the 498 | * fixed structure, as well as the variable sized arrays that hold the PWIP 499 | * matrices 500 | */ 501 | int elements_per_row = ELEMENTS_PER_ROW(num_bits); 502 | size_t size = sizeof(fnr_expanded_key) + 2 * elements_per_row * (num_bits + 1); 503 | fnr_expanded_key *key = malloc( size ); 504 | if (!key) { 505 | return NULL; 506 | } 507 | 508 | /* Store the various blocksize-dependent constants */ 509 | 510 | /* The number of bytes (not counting the last byte) */ 511 | key->full_bytes = (num_bits-1)/8; 512 | /* The number of elements (not counting the last one */ 513 | key->full_elements = key->full_bytes; /*element == unsigned char */ 514 | /* The bits that are used in the last byte */ 515 | key->final_mask = 0xff & ((1<<((num_bits+7)%8 + 1)) - 1); 516 | /* The number of elements (not counting the last one */ 517 | key->final_element_mask = key->final_mask; /* == unsigned char */ 518 | /* The size of the block (in bits) */ 519 | key->num_bits = num_bits; 520 | /* The size of the structure */ 521 | key->size = size; 522 | /* Where the inverse PWIP matrix is stored (the forward PWIP is */ 523 | /* immediately after the fixed structure) */ 524 | key->green = key->red + elements_per_row * (num_bits + 1); 525 | 526 | /* Expand the AES key */ 527 | if (AES_set_encrypt_key(aes_key, aes_key_size, &key->expanded_aes_key) != 0) { 528 | free(key); 529 | return NULL; 530 | } 531 | 532 | key->aes_key = calloc(1, aes_key_size + 1); 533 | memcpy(key->aes_key, aes_key, aes_key_size); 534 | 535 | /* Now the hard part; select an affine function, and its inverse */ 536 | struct pwip_stream stream; 537 | stream.key = key; 538 | stream.num_bits = num_bits; 539 | stream.count = 0; 540 | stream.index = BLOCKSIZE; 541 | 542 | if (!expand_red_green( &stream, key->red, key->green, num_bits )) { 543 | free(key); 544 | return NULL; 545 | } 546 | 547 | /* Ok, all done; erase any incriminating evidence and get out */ 548 | FNR_burn( &stream, sizeof stream ); 549 | 550 | return key; 551 | } 552 | 553 | /* 554 | * Safely get rid of an expanded key 555 | */ 556 | void FNR_release_key (fnr_expanded_key *key) 557 | { 558 | if (!key) return; 559 | FNR_burn( key, key->size ); 560 | free(key); 561 | } 562 | 563 | /* 564 | * This takes an arbitrary byte string, and "expands" it into a form that can 565 | * be used by the encrypt/decrypt routines 566 | * Actually, in this case, "expand" is not quite the correct terminology; 567 | * instead, it summarizes the arbitrary length string into a fixed length form; 568 | * and in such a way that any modification to the tweak will completely alter 569 | * the summary 570 | * A cryptographic hash would be perfect; we don't assume we have one of those 571 | * available. So, what we do is a variant on a CBC-MAC (with the length of the 572 | * string in front, so we don't have to worry about length extension attacks 573 | * (which wouldn't apply anyways, but still...)) 574 | */ 575 | void FNR_expand_tweak(fnr_expanded_tweak *expanded_tweak, 576 | const fnr_expanded_key *key, 577 | const void *tweak, size_t len_tweak) { 578 | unsigned char block[BLOCKSIZE] = { 0 }; 579 | 580 | block[0] = len_tweak & 0xff; 581 | block[1] = len_tweak >> 8; /* Tweaks > 255 bytes are unlikely, and */ 582 | block[2] = len_tweak >> 16; /* >64k is downright silly, but still */ 583 | block[3] = len_tweak >> 24; /* we might as well acknowledge the */ 584 | /* possibility */ 585 | block[4] = key->num_bits; /* This is so if we use the same key for two */ 586 | /* different block sizes, the transforms are unrelated */ 587 | unsigned n = 5; /* We've just placed 5 bytes into block */ 588 | const unsigned char *input = tweak; 589 | 590 | do { 591 | for (; naes_key); 601 | AES_encrypt(block, block, &key->expanded_aes_key); 602 | n = 0; 603 | 604 | } while (len_tweak > 0); 605 | 606 | memcpy( expanded_tweak, block, BLOCKSIZE-1 ); 607 | FNR_burn( block, sizeof block ); 608 | } 609 | 610 | /* 611 | * This computes a pairwise independent permutation of in, and places the 612 | * result into out 613 | * A pairwise independent permutation is a permutation that has the property 614 | * that, assuming a random (uniformly distributed key), that any two distinct 615 | * inputs A, B, and any two distinct outputs X, Y, the probability that 616 | * X=PWIP(A) and Y=PWIP(B) is uniform, that is, is 1/(2**n * (2**n-1)) 617 | * independent of A, B, X, Y 618 | * 619 | * This function actually achieves the stronger Threeway Independent 620 | * Permutation criteria, for three distinct inputs A, B, C, and three distinct 621 | * outputs X, Y, Z, the probability that X=PWIP(A), Y=PWIP(B), Z=PWIP(C) is 622 | * independent of A, B, C, X, Y, Z 623 | * 624 | * This works by using binary matrix multiplication, the input vector is 625 | * treated as a vector in GF(2); it is multiplied by a randomly (uniformly 626 | * distributed) nxn matrix of GF(2) elements, and then added with a random 627 | * vector in GF(2), resulting in a random (uniformly distributed) affine 628 | * function 629 | * 630 | * The structure of the m vector: 631 | * - The first elements_per_row elements is the constant vector (which we end 632 | * up adding at the start, not as a final step) 633 | * - Then, each successive elements_per_row set of elements this the next 634 | * row of the matrix; there are N of these rows 635 | */ 636 | static void pwip(const fnr_expanded_key *key, const element *m, 637 | const void *in, void *out) { 638 | unsigned i, j; 639 | const unsigned char *input = in; 640 | element *result = out; 641 | 642 | /* 643 | * Initialize the output with the constant vector 644 | */ 645 | unsigned elements_per_row = key->full_elements; 646 | for (i=0; ifinal_element_mask; 654 | result[i] = (result[i] & ~final_mask) | *m++; 655 | 656 | /* 657 | * Now step through the input bits one at a time; if each bit is one, xor 658 | * in the corresponding row from the matrix 659 | */ 660 | unsigned char a = 0; 661 | unsigned num_bits = key->num_bits; 662 | for (i=0; i>= 1; 666 | /* 667 | * Here, mask == 0 if the bit is 0, mask == 0xff if the bit is one 668 | * An 'if' statement would be clearer; however this implementation has 669 | * the advantage that it runs in constant time and with constant 670 | * memory references 671 | */ 672 | for (j=0; j<=elements_per_row; j++) { 673 | result[j] ^= mask & *m++; 674 | } 675 | } 676 | } 677 | 678 | /* 679 | * This is the actual cipher implementation. The encrypt and the decrypt 680 | * operations are identical, except for the order of the subkeys 681 | */ 682 | static void FNR_operate(const fnr_expanded_key *key,const fnr_expanded_tweak *tweak, 683 | const void *in, void *out, int round, int round_inc ) { 684 | unsigned char text[BLOCKSIZE] = { 0 }; 685 | 686 | /* 687 | * First step: run a key-dependent Pair Wise Independent Permutation on the 688 | * input block (and, at the same time, copy it to somewhere which we can 689 | * modify) 690 | */ 691 | pwip( key, key->red, in, text ); 692 | 693 | /* 694 | * Now, we run 7 rounds of Luby-Rackoff (aka a Feistel network). This is 695 | * slightly different from most implementations of LR, in that we don't 696 | * divide the block into two separate halves; instead, we use the even 697 | * bits as one half and the odd bits as other half, and we don't swap 698 | * them; instead, we alternate between rounds which half we use as the 699 | * input to our random function, and which half we xor the output of the 700 | * random function into. Since we have an odd number of rounds, this 701 | * all works out. 702 | * Nits: if the block we're encrypting has an odd number of bits, this is 703 | * strictly speaking an unbalanced Feistel (if unbalanced only by a single 704 | * bit). In addition, if we're encrypting a single bit, this really isn't 705 | * a Feistel at all (because one half is empty). 706 | */ 707 | int i; 708 | unsigned char block[BLOCKSIZE]; /* This is the temp block we use to */ 709 | /* compute the LR round function */ 710 | unsigned mask = 0x55; /* This determines whether the even bits or */ 711 | /* the odd bits are the 'active' half */ 712 | unsigned full_bytes = key->full_bytes; /* This is the number of bytes */ 713 | /* make up the block, not counting the last */ 714 | /* (possibly partial) byte */ 715 | unsigned input_len = (full_bytes + 1); /* This is the number of chars in input */ 716 | unsigned final_mask = key->final_mask; /* This indicates which bits of */ 717 | /* the (possibly partial) last byte actually */ 718 | /* participate */ 719 | 720 | for (i=0; iaes_key); 751 | AES_encrypt(block, block, &key->expanded_aes_key); 752 | 753 | /* 754 | * Step 4: swap the 'active bits' (so that if the even bits were 755 | * active, now the odd bits will be) 756 | */ 757 | mask ^= 0xff; 758 | 759 | /* 760 | * Step 5: xor the bits from the temp block into the 'active bits' from 761 | * the block, and leave the bits that are not 'active' alone. Since we 762 | * just swapped the active bits, the active bits will be precisely 763 | * those bits we didn't send through the AES function 764 | * Note that this may also overwrite a few unused bits in the last 765 | * partial byte; since we'll never depend on those, that doesn't cause 766 | * a problem 767 | */ 768 | for (j=0; j<=full_bytes; j++) { 769 | text[j] ^= block[j] & mask; 770 | } 771 | 772 | } 773 | 774 | /* 775 | * Last step: run the inverse key-dependent Pair Wise Independent 776 | * Permutation on the output block (and, at the same time, copy it to where 777 | * we were asked) 778 | */ 779 | pwip( key, key->green, text, out ); 780 | 781 | /* Zeroize temp data; it's good crypto hygiene */ 782 | FNR_burn( block, sizeof block ); 783 | FNR_burn( text, sizeof text ); 784 | } 785 | 786 | void FNR_init(void){ 787 | /* Initialise the library */ 788 | ERR_load_crypto_strings(); 789 | OpenSSL_add_all_algorithms(); 790 | OPENSSL_config(NULL); 791 | } 792 | 793 | void FNR_shut(void){ 794 | /* Clean up */ 795 | EVP_cleanup(); 796 | ERR_free_strings(); 797 | } 798 | 799 | void FNR_encrypt(const fnr_expanded_key *key,const fnr_expanded_tweak *tweak, const void *plaintext, void *ciphertext) { 800 | /* Run the cipher, going through (7) rounds 0,1,2,3,4,5,6 */ 801 | FNR_operate( key, tweak, plaintext, ciphertext, 0, 1 ); 802 | } 803 | 804 | void FNR_decrypt(const fnr_expanded_key *key,const fnr_expanded_tweak *tweak, const void *ciphertext, void *plaintext) { 805 | /* Run the cipher, going through (7) rounds 6,5,4,3,2,1,0 */ 806 | FNR_operate( key, tweak, ciphertext, plaintext, N_ROUND-1, -1 ); 807 | } 808 | 809 | -------------------------------------------------------------------------------- /src/fnr.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libFNR - A reference implementation library for FNR encryption . 3 | * 4 | * FNR represents "Flexible Naor and Reingold" 5 | 6 | * FNR is a small domain block cipher to encrypt small domain 7 | * objects ( < 128 bits ) like IPv4, MAC, Credit Card numbers etc. 8 | 9 | * FNR is designed by Sashank Dara (sadara@cisco.com), Scott Fluhrer (sfluhrer@cisco.com) 10 | * 11 | * fnr.h is written by Scott Fluhrer 12 | * 13 | * Copyright (C) 2014 , Cisco Systems Inc. 14 | * 15 | * This library is free software; you can redistribute it and/or 16 | * modify it under the terms of the GNU Lesser General Public 17 | * License as published by the Free Software Foundation; either 18 | * version 2.1 of the License, or (at your option) any later version. 19 | * 20 | * This library is distributed in the hope that it will be useful, 21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23 | * Lesser General Public License for more details. 24 | * 25 | * You should have received a copy of the GNU Lesser General Public 26 | * License along with this library; if not, write to the Free Software 27 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 28 | * 29 | **/ 30 | #ifndef HEADER_FNR_H_ 31 | #define HEADER_FNR_H_ 32 | 33 | /* 34 | * This is a utility to do small block encryption, with a variable sized block 35 | * between 1 and 128 bits, and with no ciphertext expansion (that is, the 36 | * ciphertext is precisely the same length as the plaintext) 37 | * 38 | * It isn't very efficient (it's not; after all, every encryption or decryption 39 | * operation involves 7 calls to AES); it is designed to be secure. 40 | * 41 | * Here are the concepts behind it: 42 | * - key -- This is the secret used to specify how to transform. This is the 43 | * part that you share between the encryptor and decryptor, and what 44 | * needs to be kept secret from anyone listening in. We use the same 45 | * key sizes as AES (128, 192, 256 bits; expressed as a byte string). 46 | * 47 | * - tweak -- This is a parameter that modifies how the encryption is done. 48 | * This is designed so that the same key can be used to protect 49 | * different fields, in such a way so that if someone learns that 50 | * plaintext xxx corresponds to ciphertext yyy in context A, they still 51 | * have no information what yyy means in context B. The idea is that 52 | * you'd use a string the identifies the context as the tweak. As such, 53 | * the tweak has the following properties: 1) the encryption process 54 | * with the same key and two different tweaks are unrelated; 2) there is 55 | * no security problem with making the tweak public (unlike the key), 56 | * 3) the tweak is cheap to update (a lot cheaper than the key, in this 57 | * case) 58 | * 59 | * We support arbitrary bytestrings as tweaks 60 | * 61 | * - plaintext/ciphertext -- These are n-bit binary fields, with n being 62 | * between 1 and 128 (and you specify it while expanding the key). 63 | * These are represented by strings of unsigned char's, with each 64 | * unsigned char holding 8 bits. If n is not a multiple of 8, then we 65 | * handle the last partial byte by using the lsbits in the last byte; 66 | * the msbits of that unsigned char are assumed not to be a part of the 67 | * plaintext/ciphertext 68 | * 69 | * Now, encryption/decryption is determanistic; if we encrypt the same 70 | * plaintext twice with the same key and tweak, you will always get the same 71 | * ciphertext. This is a side effect of not having any ciphertext expansion, 72 | * there are 2**N possible plaintexts and 2**N possible ciphertexts, and so 73 | * (for a fixed key/tweak) there has to be a 1:1 mapping. 74 | * 75 | * Here's how you use it: 76 | * 77 | * Step 1: convert your key (128, 192 or 256 bit -- this is based on AES, and 78 | * this key will be directly fed to it) into expanded form: 79 | * 80 | * fnr_expanded_key *key = FNR_expand_key( aes_key, aes_key_size, 81 | * block_size ); 82 | * if (!key) error_handling(); 83 | * 84 | * The block_size parameter is the of blocks we'll encrypt with this key; it 85 | * must be a value between 1 and 128 bits. Why anyone would want to encrypt 86 | * a 1 bit block, I have no idea, but still... 87 | * 88 | * You can reuse this key everytime you need to encrypt or decrypt with this 89 | * key and this block size. If you want to use the same key with a different 90 | * block size, that's fine (that won't cause a security problem), but you'll 91 | * need to reexpand the key 92 | * 93 | * Step 2: expand your tweak (which is public data that modifies how the 94 | * encryption is done; one way of thinking of this is to look at it as another 95 | * part of the key, but one which can be made public, and which is cheap to 96 | * change): 97 | * 98 | * fnr_expanded_tweak tweak; 99 | * FNR_expand_tweak(&tweak, key, arbitrary_bytestring, length_of_bytestring); 100 | * 101 | * The tweak may consist of an arbitrary bytestring. 102 | * 103 | * If you use the same tweak for multiple encryptions/decryptions, you can use 104 | * the same expanded tweak. 105 | * 106 | * If you don't have a tweak, you need to expand a 0-length tweak. Perhaps we 107 | * could have the encrypt/decrypt routines interpet a NULL tweak as the 108 | * 0-length; we currently don't bother (as 0-length tweaks may not occur often 109 | * enough) 110 | * 111 | * Step 3: encrypt and decrypt your data 112 | * 113 | * FNR_encrypt(key, &tweak, plaintext, ciphertext); 114 | * FNR_decrypt(key, &tweak, ciphertext, plaintext); 115 | * 116 | * Encrypting/decrypting in place (plaintext==ciphertext) is allowed; because 117 | * the plaintext and the ciphertext are the same size, you may want to do this 118 | * 119 | * Here, plaintext and ciphertext are the number of bits long you specified 120 | * when you expanded the key. Now, if you specified a length that's not a 121 | * multiple of 8, here's how we handle that case: if you specify such an odd 122 | * size N, we take all the N/8 bytes, plus the remaining N%8 lsbits from the 123 | * next byte. When we write, we are careful not to disturb any bits outside the 124 | * N bit region. For example, if we have a 4 bit ciphertext, we'll update the 125 | * lower 4 bits of *ciphertext, and leave the remaining upper 4 bits 126 | * undisturbed. 127 | * 128 | * Step last: when you're done with the key, you discard it with: 129 | * 130 | * FNR_release_key(key); 131 | * 132 | * (there's no need to release the expanded tweak) 133 | */ 134 | 135 | /* The structure of an expanded key; its contents are private */ 136 | typedef struct fnr_expanded_key_st fnr_expanded_key; 137 | 138 | /* 139 | * This is the 'expanded tweak'; that is, the tweak summarized in a form that 140 | * we can give to the encryption/decryption routine 141 | */ 142 | typedef struct fnr_expanded_tweak_st{ 143 | unsigned char tweak[15]; 144 | } fnr_expanded_tweak; 145 | 146 | /* 147 | * This takes an aes key (aes_key ad aes_key_size), and expands it into an 148 | * expanded form for use 149 | * Parameters: 150 | * aes_key - This is the 128 bit (16 byte), 192 bit (24 byte) or 256 bit (32 151 | * byte) key. 152 | * aes_key_size - This is the length of the above key, in bits. That is, it 153 | * is either 128, 192 or 256 154 | * num_text_bits - This is the size of the plaintext/ciphertexts that we will 155 | * encrypt, in *bits*. That is, it is between 1 and 128 (using a 156 | * 1 bit plaintext/ciphertexts isn't greatly encouraged, but it is 157 | * allowed) 158 | * This returns the expanded key on success, NULL on failure 159 | */ 160 | fnr_expanded_key *FNR_expand_key(const void *aes_key, unsigned int aes_key_size, 161 | size_t num_text_bits); 162 | 163 | /* 164 | * This frees an expanded key. It should be called when you're done with the key 165 | * (as the key expansion malloc's memory) 166 | * Parameters: 167 | * key - The expanded key to deallocate (and release) 168 | */ 169 | void FNR_release_key(fnr_expanded_key *key); 170 | 171 | /* 172 | * This takes a tweak, and expands it 173 | * A zero-length tweak is perfectly legal 174 | * Parameters: 175 | * expanded_tweak - This is where to place the expanded tweak. 176 | * key - This is the expanded key that the tweak will be used with. 177 | * tweak - This is tweak to expand. 178 | * len_tweak - This is the length of the tweak, in bytes. 179 | */ 180 | void FNR_expand_tweak(fnr_expanded_tweak *expanded_tweak, 181 | const fnr_expanded_key *key, 182 | const void *tweak, size_t len_tweak ); 183 | /* 184 | * This method initializes and loads the needed algos 185 | * and sets the stage 186 | */ 187 | void FNR_init(void); 188 | 189 | /* 190 | * This method frees up and cleans 191 | */ 192 | 193 | void FNR_shut(void); 194 | /* 195 | * This encrypts a message using the expanded key and tweak 196 | * Parameters: 197 | * key - The expanded key 198 | * tweak - The expanded tweak 199 | * plaintext - The value to be encrypted 200 | * ciphertext - Where to place the result of the encryption 201 | * 202 | * Encrypting in place (plaintext==ciphertext) is allowed 203 | */ 204 | void FNR_encrypt(const fnr_expanded_key *key,const fnr_expanded_tweak *tweak, 205 | const void *plaintext, void *ciphertext); 206 | /* 207 | * This decrypts a message using the expanded key and tweak 208 | * Parameters: 209 | * key - The expanded key 210 | * tweak - The expanded tweak 211 | * ciphertext - The value to be decrypted 212 | * plaintext - Where to place the result of the decryption 213 | * 214 | * Decrypting in place (ciphertext==plaintext) is allowed 215 | */ 216 | void FNR_decrypt(const fnr_expanded_key *key, const fnr_expanded_tweak *tweak, 217 | const void *ciphertext, void *plaintext); 218 | 219 | void FNR_handle_errors(void); 220 | 221 | void FNR_burn( void *v, size_t n ); 222 | #endif /* HEADER_FNR_H_ */ 223 | -------------------------------------------------------------------------------- /test/Makefile.am: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2014 Cisco Systems, Inc. 2 | 3 | bin_PROGRAMS = ipv4test timestamptest bench 4 | 5 | ipv4test_SOURCES = test_ipv4.c 6 | ipv4test_CPPFLAGS = -I$(top_srcdir)/src 7 | ipv4test_LDADD = $(top_builddir)/src/libfnr.la 8 | ipv4test_DEPENCENCIES = $(ipv4test_LDADD) 9 | 10 | timestamptest_SOURCES = test_timestamp.c 11 | timestamptest_CPPFLAGS = -I$(top_srcdir)/src 12 | timestamptest_LDADD = $(top_builddir)/src/libfnr.la 13 | timestamptest_DEPENCENCIES = $(timestamptest_LDADD) 14 | 15 | bench_SOURCES = bench.c 16 | bench_CPPFLAGS = -I$(top_srcdir)/src 17 | bench_LDADD = $(top_builddir)/src/libfnr.la 18 | bench_DEPENCENCIES = $(bench_LDADD) 19 | 20 | EXTRA_DIST = generate_ipv4.py 21 | 22 | if DEBUG 23 | AM_CFLAGS = -g3 -O0 -DDEBUG 24 | AM_CXXFLAGS = -g3 -O0 -DDEBUG 25 | else 26 | AM_CFLAGS = -O2 27 | AM_CXXFLAGS = -O2 28 | endif 29 | -------------------------------------------------------------------------------- /test/bench.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libFNR - A reference implementation library for FNR encryption mode. 3 | * 4 | * FNR represents "Flexible Naor and Reingold" mode 5 | * 6 | * FNR is a small domain block cipher to encrypt small domain 7 | * objects ( < 128 bits ) like IPv4, MAC, Credit Card numbers etc. 8 | * 9 | * FNR is designed by Sashank Dara (sadara@cisco.com), Scott Fluhrer (sfluhrer@cisco.com) 10 | * 11 | * Copyright (C) 2014-2015, Cisco Systems, Inc. 12 | * 13 | * This library is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Lesser General Public 15 | * License as published by the Free Software Foundation; either 16 | * version 2.1 of the License, or (at your option) any later version. 17 | * 18 | * This library is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 | * Lesser General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU Lesser General Public 24 | * License along with this library; if not, write to the Free Software 25 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 26 | * 27 | **/ 28 | 29 | /* 30 | * @mgurevin : This is a simple benchmark functions for encryprion and decryption methods. 31 | */ 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include "fnr.h" 43 | 44 | static double get_time() 45 | { 46 | struct timeval t; 47 | struct timezone tzp; 48 | 49 | gettimeofday(&t, &tzp); 50 | 51 | return t.tv_sec + (t.tv_usec * 1e-6); 52 | } 53 | 54 | void print_hex(const unsigned char *data, size_t len) { 55 | size_t i; 56 | 57 | for (i = 0; i < len; i++) 58 | { 59 | if (i > 0) { 60 | printf(":"); 61 | } 62 | 63 | printf("%02X", data[i]); 64 | } 65 | } 66 | 67 | int main (int argc, char *argv[]) 68 | { 69 | int i; 70 | char *passphrase = NULL; 71 | char *salt = NULL; 72 | char *tweak_str = NULL; 73 | int block_size = -1; 74 | int iterations = -1; 75 | static unsigned char aes_key[16]; 76 | unsigned char encrypted[16]; 77 | 78 | unsigned char raw[] = { 0x56, 0x9c, 0x3c, 0x57, 0xb3, 0x09, 0xdb, 0xba, 0x59, 0x65, 0x35, 0xff, 0xb5, 0x7c, 0x5a, 0x24 }; 79 | 80 | while ((i = getopt(argc, argv, "p:s:t:b:i:")) != -1) { 81 | switch (i) { 82 | case 'p': 83 | passphrase = optarg; 84 | break; 85 | 86 | case 's': 87 | salt = optarg; 88 | break; 89 | 90 | case 't': 91 | tweak_str = optarg; 92 | break; 93 | 94 | case 'b': 95 | block_size = atoi(optarg); 96 | break; 97 | 98 | case 'i': 99 | iterations = atoi(optarg); 100 | break; 101 | 102 | default: 103 | fprintf(stderr, "Usage: %s -p -s -t -b -i \n", argv[0]); 104 | return EXIT_FAILURE; 105 | } 106 | } 107 | 108 | if (passphrase == NULL | salt == NULL | tweak_str == NULL | block_size == -1 | iterations == -1) { 109 | fprintf(stderr, "Usage: %s -p -s -t -b -i \n", argv[0]); 110 | return EXIT_FAILURE; 111 | } 112 | 113 | printf("Passphrase: %s (", passphrase); print_hex(passphrase, strlen(passphrase)); printf(")\n"); 114 | printf("Salt : %s (", salt); print_hex(salt, strlen(salt)); printf(")\n"); 115 | printf("Tweak : %s (", tweak_str); print_hex(tweak_str, strlen(tweak_str)); printf(")\n"); 116 | printf("numBits : %d\n", block_size); 117 | printf("Iterations: %d\n", iterations); 118 | printf("-----------------------------------------------------------\n"); 119 | 120 | if (PKCS5_PBKDF2_HMAC_SHA1(passphrase, strlen(passphrase), (unsigned char *) salt, strlen(salt), 1000, 128, aes_key) != 1) { 121 | fprintf(stderr, "Generating PBKDF2 AES key has been failed.\n"); 122 | return EXIT_FAILURE; 123 | } 124 | 125 | printf("AES Key : "); print_hex(aes_key, 16); printf("\n"); 126 | printf("RAW Data : "); print_hex(raw, 16); printf("\n"); 127 | 128 | FNR_init(); 129 | 130 | fnr_expanded_key *key = FNR_expand_key(aes_key, 128, block_size); 131 | if (!key) { 132 | fprintf(stderr, "Expanding AES key has been failed.\n"); 133 | FNR_shut(); 134 | return EXIT_FAILURE; 135 | } 136 | 137 | fnr_expanded_tweak tweak; 138 | FNR_expand_tweak(&tweak, key, (void*) tweak_str, strlen(tweak_str)); 139 | 140 | FNR_burn(encrypted, 16); 141 | FNR_encrypt(key, &tweak, &raw, &encrypted); 142 | printf("Encrypted : "); print_hex(encrypted, 16); printf("\n"); 143 | printf("-----------------------------------------------------------\n"); 144 | 145 | 146 | printf("Begin encryption benchmark..."); 147 | double begin = get_time(); 148 | for (i = 0; i < iterations; i++) { 149 | FNR_encrypt(key, &tweak, &raw, &encrypted); 150 | } 151 | double elapsed = get_time() - begin; 152 | printf(" Completed.\n"); 153 | 154 | double tp_encryption = iterations / elapsed; 155 | 156 | printf("Begin decryption benchmark... "); 157 | begin = get_time(); 158 | for (i = 0; i < iterations; i++) { 159 | FNR_decrypt(key, &tweak, &encrypted, &raw); 160 | } 161 | elapsed = get_time() - begin; 162 | printf("Completed.\n\n"); 163 | 164 | double tp_decryption = iterations / elapsed; 165 | 166 | printf("Encryption: %f ops/s\n", tp_encryption); 167 | printf("Decryption: %f ops/s\n", tp_decryption); 168 | 169 | FNR_release_key(key); 170 | FNR_shut(); 171 | 172 | return EXIT_SUCCESS; 173 | } -------------------------------------------------------------------------------- /test/generate_ipv4.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import sys 3 | 4 | """ 5 | * libFNR - A reference implementation library for FNR encryption . 6 | * 7 | * FNR represents \"Flexible Naor and Reingold\" 8 | 9 | * FNR is a small domain block cipher to encrypt small domain 10 | * objects ( < 128 bits ) like IPv4, MAC, Credit Card numbers etc. 11 | 12 | * FNR is designed by Sashank Dara (sadara@cisco.com), Scott Fluhrer (sfluhrer@cisco.com) 13 | * 14 | * generate_ipv4.py has been written by Kaushal Bhandankar (kbhandan@cisco.com) 15 | * 16 | * Copyright (C) 2014 , Cisco Systems Inc. 17 | * 18 | * This library is free software; you can redistribute it and/or 19 | * modify it under the terms of the GNU Lesser General Public 20 | * License as published by the Free Software Foundation; either 21 | * version 2.1 of the License, or (at your option) any later version. 22 | * 23 | * This library is distributed in the hope that it will be useful, 24 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 26 | * Lesser General Public License for more details. 27 | * 28 | * You should have received a copy of the GNU Lesser General Public 29 | * License along with this library; if not, write to the Free Software 30 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 31 | * 32 | """ 33 | 34 | def ipRange(start_ip, number): 35 | start = list(map(int, start_ip.split("."))) 36 | temp = start 37 | ip_range = [] 38 | 39 | ip_range.append(start_ip) 40 | for i in range(1, number): 41 | start[3] += 1 42 | for i in (3, 2, 1): 43 | if temp[i] == 256: 44 | temp[i] = 0 45 | temp[i-1] += 1 46 | ip_range.append(".".join(map(str,temp))) 47 | return ip_range 48 | 49 | def main(argv): 50 | if(len(sys.argv) < 3): 51 | print "Usage: python generate_ipv4.py " 52 | print "Eg: python generate_ipv4.py 192.168.1.1 5" 53 | return 54 | 55 | ip_range = ipRange(sys.argv[1], int(sys.argv[2])) 56 | f = open('raw-ips','w') 57 | f.write(sys.argv[2] + '\n') 58 | for ip in ip_range: 59 | f.write(ip + '\n') 60 | f.close() 61 | 62 | if __name__ == "__main__": 63 | main(sys.argv[1:]) 64 | -------------------------------------------------------------------------------- /test/raw-ips: -------------------------------------------------------------------------------- 1 | 5 2 | 192.168.1.0 3 | 192.168.1.1 4 | 192.168.1.2 5 | 192.168.1.3 6 | 192.168.1.4 7 | -------------------------------------------------------------------------------- /test/raw-timestamps: -------------------------------------------------------------------------------- 1 | 2015-02-16T22:36:00 2 | 2011-08-16T22:36:00 3 | 2005-04-16T20:36:00 4 | 2010-07-10T15:35:00 5 | 2015-01-16T22:36:00 6 | 2001-03-16T12:30:00 7 | 1998-05-13T22:36:00 8 | 2003-06-12T22:36:00 9 | 2017-09-18T22:36:00 10 | 1997-08-19T10:36:58 11 | 2019-07-26T22:50:39 12 | 2022-06-06T22:36:00 13 | 2030-05-20T22:36:00 14 | 2000-04-10T22:36:00 15 | 1990-03-11T22:36:00 16 | -------------------------------------------------------------------------------- /test/test_ipv4.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libFNR - A reference implementation library for FNR encryption . 3 | * 4 | * FNR represents "Flexible Naor and Reingold" 5 | 6 | * FNR is a small domain block cipher to encrypt small domain 7 | * objects ( < 128 bits ) like IPv4, MAC, Credit Card numbers etc. 8 | 9 | * FNR is designed by Sashank Dara (sadara@cisco.com), Scott Fluhrer (sfluhrer@cisco.com) 10 | * 11 | * test_ipv4.c is written by Kaushal Bhandankar (kbhandan@cisco.com) 12 | * 13 | * Copyright (C) 2014 , Cisco Systems Inc. 14 | * 15 | * This library is free software; you can redistribute it and/or 16 | * modify it under the terms of the GNU Lesser General Public 17 | * License as published by the Free Software Foundation; either 18 | * version 2.1 of the License, or (at your option) any later version. 19 | * 20 | * This library is distributed in the hope that it will be useful, 21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23 | * Lesser General Public License for more details. 24 | * 25 | * You should have received a copy of the GNU Lesser General Public 26 | * License along with this library; if not, write to the Free Software 27 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 28 | * 29 | **/ 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include "fnr.h" 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | void generate_master_key(char* passwd, char* key) { 44 | unsigned char salt[16]; 45 | if(!(RAND_bytes(salt, sizeof(salt)))) { 46 | printf("ERROR: call to RAND_bytes() failed\n"); 47 | exit(1); 48 | } 49 | PKCS5_PBKDF2_HMAC_SHA1(passwd, strlen(passwd), (unsigned char*)salt, strlen(salt), 1000, 16, key); 50 | } 51 | 52 | /*convert the raw IP from a.b.c.d format to unsigned int format.*/ 53 | unsigned int ipv4_rank(char * ip_str){ 54 | unsigned int a,b,c,d; 55 | sscanf(ip_str, "%d.%d.%d.%d", &a, &b, &c, &d); 56 | return (a << 24) + (b << 16) + (c << 8) + d; 57 | } 58 | 59 | /*convert the raw IP from unsigned int format to a.b.c.d format.*/ 60 | int ipv4_derank(char* ip_str, unsigned int ip){ 61 | unsigned int a,b,c,d; 62 | a = ip >> 24; 63 | b = (ip << 8) >> 24; 64 | c = (ip << 16) >> 24; 65 | d = (ip << 24) >> 24; 66 | return snprintf(ip_str, 16, "%d.%d.%d.%d", a, b, c, d); 67 | } 68 | 69 | int main(int argc, char * argv[]) { 70 | static unsigned char orig_key[16] = {0}; 71 | char *passwd = NULL , *tweak_str = NULL , *filename = NULL, ip_str[16] = {0}; 72 | int c, ret ; 73 | FILE * f; 74 | unsigned int *p_raw_addr = NULL, raw_addr, encrypted_addr; 75 | unsigned int num_ip_addresses = 0, loop_count = 0; 76 | char no_ip_str[10]; 77 | #ifdef DEBUG 78 | char ip_address_str[16]; 79 | #endif 80 | 81 | if (argc != 7) { 82 | fprintf(stderr, "usage: ipv4test -p passwd -t tweak -f raw-trace-file\n"); 83 | exit(-1); 84 | } 85 | 86 | while ((c = getopt (argc, argv, "p:t:f:")) != -1){ 87 | switch (c) 88 | { 89 | case 'p': 90 | passwd = optarg; 91 | break; 92 | case 't': 93 | tweak_str = optarg; 94 | break; 95 | case 'f': 96 | filename = optarg; /* Could be used when inputs are read from file */ 97 | break; 98 | case '?': 99 | if (optopt == 'c') 100 | fprintf (stderr, "Option -%c requires an argument.\n", optopt); 101 | else if (isprint (optopt)) 102 | fprintf (stderr, "Unknown option `-%c'.\n", optopt); 103 | else 104 | fprintf (stderr, 105 | "Unknown option character `\\x%x'.\n", 106 | optopt); 107 | return 1; 108 | default: 109 | abort (); 110 | } 111 | } 112 | 113 | #ifdef DEBUG 114 | printf ("%s, %s, %s\n", passwd, tweak_str, filename); 115 | printf("-----------------------------------------------------------\n"); 116 | #endif 117 | if ((f = fopen(filename,"r")) == NULL) { 118 | fprintf(stderr,"Cannot open file %s\n", argv[1]); 119 | exit(-2); 120 | } 121 | 122 | /* Init */ 123 | FNR_init(); 124 | 125 | /* Initialize the keys and tweaks */ 126 | generate_master_key(passwd,orig_key); 127 | fnr_expanded_key *key = FNR_expand_key(orig_key, 128, 32); 128 | if (!key) { 129 | fprintf( stderr, "Error expanding key\n" ); 130 | return 0; 131 | } 132 | 133 | fnr_expanded_tweak tweak; 134 | FNR_expand_tweak(&tweak, key, (void*)tweak_str, strlen(tweak_str)); 135 | 136 | fgets(no_ip_str, 10, f); 137 | num_ip_addresses = atoi(no_ip_str); 138 | 139 | p_raw_addr = (unsigned int *)malloc(sizeof(int)* num_ip_addresses); 140 | if(NULL == p_raw_addr){ 141 | fprintf(stderr,"Cannot allocate memory for %d IP addresses\n", num_ip_addresses); 142 | exit(-3); 143 | } 144 | 145 | while(fgets(ip_str, 16 , f) != NULL) { 146 | p_raw_addr[loop_count] = ipv4_rank(ip_str); 147 | FNR_burn(ip_str, 16); 148 | ++loop_count; 149 | } 150 | 151 | loop_count = 0; 152 | 153 | clock_t start, end; 154 | double cpu_time_used; 155 | 156 | //Performance test start 157 | start = clock(); 158 | while(loop_count < num_ip_addresses){ 159 | 160 | encrypted_addr = raw_addr = p_raw_addr[loop_count]; 161 | 162 | #ifdef DEBUG 163 | ipv4_derank(ip_address_str, raw_addr); 164 | printf("Input\t\t%s\n", ip_address_str); 165 | #endif 166 | 167 | FNR_encrypt(key, &tweak, &raw_addr, &encrypted_addr); 168 | 169 | #ifdef DEBUG 170 | ipv4_derank(ip_address_str, encrypted_addr); 171 | printf("Ciphertext\t%s\n", ip_address_str); 172 | #endif 173 | 174 | FNR_decrypt(key, &tweak, &encrypted_addr, &raw_addr); 175 | 176 | #ifdef DEBUG 177 | ipv4_derank(ip_address_str, raw_addr); 178 | printf("Plaintext\t%s\n", ip_address_str); 179 | printf("-----------------------------------------------------------\n"); 180 | 181 | if(raw_addr != p_raw_addr[loop_count]){ 182 | printf("ERROR: decrypt output does not match the user input\n"); 183 | exit(-4); 184 | } 185 | #endif 186 | 187 | ++loop_count; 188 | } 189 | 190 | end = clock(); 191 | cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC; 192 | //Performance test end 193 | 194 | //printf("CPU time used %f\n", cpu_time_used); 195 | printf("%d , %f\n",num_ip_addresses, cpu_time_used); 196 | free(p_raw_addr); 197 | FNR_release_key(key); 198 | FNR_shut(); 199 | return 0; 200 | } 201 | -------------------------------------------------------------------------------- /test/test_timestamp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libFNR - A reference implementation library for FNR encryption. 3 | * 4 | * FNR represents "Flexible Naor and Reingold" 5 | * 6 | * FNR is a small domain block cipher to encrypt small domain 7 | * objects ( < 128 bits ) like IPv4, MAC, Credit Card numbers etc. 8 | * 9 | * FNR is designed by Sashank Dara (sadara@cisco.com), Scott Fluhrer (sfluhrer@cisco.com) 10 | * 11 | * test_timestamp.c is written by Anand Verma [verma.anand09@gmail.com]. 12 | * 13 | * Thanks to Prakruti C [prak1090@gmail.com] for providing reference 14 | * code in c++ for date format conversions. 15 | * 16 | * Copyright (C) 2014 , Cisco Systems Inc. 17 | * 18 | * This library is free software; you can redistribute it and/or 19 | * modify it under the terms of the GNU Lesser General Public 20 | * License as published by the Free Software Foundation; either 21 | * version 2.1 of the License, or (at your option) any later version. 22 | * 23 | * This library is distributed in the hope that it will be useful, 24 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 26 | * Lesser General Public License for more details. 27 | * 28 | * You should have received a copy of the GNU Lesser General Public 29 | * License along with this library; if not, write to the Free Software 30 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 31 | */ 32 | 33 | /* 34 | * @pyav : Application to test timestamp encryption in fnr mode. 35 | * The format of the date in provided file should be as following: 36 | * 2004-09-16T23:59:58 37 | */ 38 | 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include "fnr.h" 48 | 49 | #define TRUE 1 50 | #define FALSE 0 51 | #define SUCCESS 0 52 | #define FAILURE 1 53 | #define KEYLEN 16 54 | #define NUM_BITS 8 55 | #define MAX_BYTES 16 56 | #define ITERATION 1000 57 | #define AES_KEY_SIZE 128 58 | #define MAX_DATA_LEN 1024 59 | #define ARGS_LIST_COUNT 7 60 | 61 | static int generate_master_key (char *passwd, char *key) 62 | { 63 | unsigned char salt[16]; 64 | 65 | if (!(RAND_bytes (salt, sizeof (salt)))) { 66 | fprintf (stderr, "Call to %s failed\n", __func__); 67 | return 0; /* 0 designates error here */ 68 | } 69 | 70 | return (PKCS5_PBKDF2_HMAC_SHA1(passwd, strlen (passwd), 71 | (unsigned char *) salt, strlen (salt), ITERATION, KEYLEN, key)); 72 | } 73 | 74 | int main (int argc, char *argv[]) 75 | { 76 | int c; 77 | int flag = FALSE; 78 | int yr; 79 | int mn; 80 | int dt; 81 | int hr; 82 | int min; 83 | int sec; 84 | 85 | char datestr[21] = {0}; 86 | size_t len = 0; 87 | size_t str_len; 88 | ssize_t read; 89 | char *passwd = NULL; 90 | char *tweak_str = NULL; 91 | char *filename = NULL; 92 | 93 | clock_t start; 94 | clock_t end; 95 | double cpu_time; 96 | time_t t_of_day; 97 | time_t time_t_data; 98 | uint32_t raw_data; 99 | uint32_t encrypted_data; 100 | uint32_t time; 101 | struct tm t; 102 | FILE * stream = NULL; 103 | static unsigned char orig_key[32] = {0}; 104 | 105 | fnr_expanded_key *key = NULL; 106 | fnr_expanded_tweak tweak; 107 | 108 | if (argc != ARGS_LIST_COUNT) { 109 | fprintf (stderr, "Usage: ./test/timestamptest -p -t " 110 | "-f \n"); 111 | return FAILURE; 112 | } 113 | 114 | while ((c = getopt (argc, argv, "p:t:f:")) != -1) { 115 | switch (c) { 116 | case 'p': 117 | passwd = optarg; 118 | break; 119 | 120 | case 't': 121 | tweak_str = optarg; 122 | break; 123 | 124 | case 'f': 125 | filename = optarg; 126 | break; 127 | 128 | default: 129 | fprintf (stderr, "Usage: ./test/timestamptest -p -t " 130 | "-f "); 131 | return FAILURE; 132 | } 133 | } 134 | 135 | stream = fopen (filename, "r"); 136 | if (stream == NULL) { 137 | perror ("fopen"); 138 | exit (EXIT_FAILURE); 139 | } 140 | 141 | /* Init */ 142 | FNR_init (); 143 | 144 | if (generate_master_key (passwd, (char *) orig_key) == 0) { 145 | fprintf (stderr, "Key derivation function failed\n"); 146 | fclose (stream); 147 | return FAILURE; 148 | } 149 | 150 | key = FNR_expand_key (orig_key, AES_KEY_SIZE, 151 | NUM_BITS * sizeof (t_of_day)); 152 | if (key == NULL) { 153 | fprintf (stderr, "Error expanding key\n"); 154 | fclose (stream); 155 | return FAILURE; 156 | } 157 | 158 | FNR_expand_tweak (&tweak, key, (void *) tweak_str, strlen (tweak_str)); 159 | 160 | start = clock(); 161 | if (start == -1) { 162 | flag = TRUE; 163 | } 164 | 165 | printf ("\n"); 166 | while (fgets (datestr, sizeof (datestr), stream) != NULL) { 167 | len = strlen (datestr); 168 | if ((len != 0) && (datestr[len - 1] == '\n')) { 169 | datestr[len - 1] = '\0'; 170 | if (sscanf (datestr, "%d-%d-%dT%d:%d:%d", 171 | &yr, &mn, &dt, &hr, &min, &sec) != 6) { 172 | fprintf (stderr, "sscanf didn't read six elements\n"); 173 | continue; 174 | } 175 | t.tm_year = yr - 1900; 176 | t.tm_mon = mn - 1; 177 | t.tm_mday = dt; 178 | t.tm_hour = hr; 179 | t.tm_min = min; 180 | t.tm_sec = sec; 181 | t.tm_isdst = 0; 182 | 183 | t_of_day = mktime (&t); 184 | if (t_of_day == -1) { 185 | perror ("mktime"); 186 | fclose (stream); 187 | return FAILURE; 188 | } 189 | printf ("Date: %s", ctime (&t_of_day)); 190 | printf ("Epoch value: %ld\n", t_of_day); 191 | 192 | time = htonl ((uint32_t) t_of_day); 193 | printf ("htonl (t_of_day) = %" PRIu32 "\n", time); 194 | 195 | raw_data = time; 196 | FNR_encrypt (key, &tweak, &raw_data, &encrypted_data); 197 | printf ("Encrypted data: %" PRIu32 "\n", encrypted_data); 198 | time_t_data = (time_t) encrypted_data; 199 | printf ("Encrypted date string: %s", ctime (&time_t_data)); 200 | 201 | FNR_decrypt (key, &tweak, &encrypted_data, &raw_data); 202 | printf ("Decrypted data: %" PRIu32 "\n", raw_data); 203 | raw_data = ntohl (raw_data); 204 | printf ("htonl (raw_data) = %" PRIu32 "\n", raw_data); 205 | time_t_data = (time_t) raw_data; 206 | printf ("Date: %s\n", ctime (&time_t_data)); 207 | } else { 208 | break; 209 | } 210 | } 211 | 212 | end = clock(); 213 | if ((end != -1) && (flag == FALSE)) { 214 | cpu_time = ((double) (end - start)) / CLOCKS_PER_SEC; 215 | printf ("cpu time used: %.3f seconds.\n\n", cpu_time); 216 | } else { 217 | printf ("Could not calculate processor time.\n\n"); 218 | } 219 | 220 | fclose (stream); 221 | FNR_release_key (key); 222 | FNR_shut (); 223 | return SUCCESS; 224 | } 225 | 226 | /* 227 | * End of my codes. 228 | */ 229 | 230 | --------------------------------------------------------------------------------