├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── _build ├── Dockerfile ├── linux64 │ ├── Makefile │ └── drake └── macosx64 │ ├── Makefile │ └── drake ├── drakefile ├── src ├── dopenssl │ ├── all.h │ ├── all.hh │ ├── bn.c │ ├── bn.h │ ├── bn.hh │ ├── rand.c │ ├── rand.h │ ├── rand.hh │ ├── rsa.c │ ├── rsa.h │ └── rsa.hh └── sample.c └── tests └── dopenssl ├── bn.c ├── dopenssl.h ├── rand.c └── rsa.c /.gitignore: -------------------------------------------------------------------------------- 1 | _build 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | language: c 3 | compiler: gcc 4 | services: 5 | - docker 6 | env: 7 | - DOCKER_IMAGE="infinit/dopenssl:${TRAVIS_COMMIT}" 8 | script: 9 | - cd _build/linux64 10 | - make tests 11 | - make check 12 | - make sample 13 | - ./src/sample "chiche donne nous tout" 14 | - docker build -t ${DOCKER_IMAGE} ../ 15 | after_success: 16 | - bash <(curl -s https://codecov.io/bash) 17 | - docker login -u "${DOCKER_USERNAME}" -p "${DOCKER_PASSWORD}" 18 | - docker push ${DOCKER_IMAGE} 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, infinit.io 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | * Redistributions of source code must retain the above copyright notice, this 7 | list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above copyright notice, 9 | this list of conditions and the following disclaimer in the documentation 10 | and/or other materials provided with the distribution. 11 | * Neither the name of infinit.io nor the names of its contributors may be used 12 | to endorse or promote products derived from this software without specific 13 | prior written permission. 14 | * A shipment of at least six (6) local beers (1980 mL) to infinit.io 15 | (http://open.infinit.io/beer) would be greatly appreciated as a gesture 16 | of good will. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL INFINIT.IO BE LIABLE FOR ANY DIRECT, INDIRECT, 22 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 24 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 25 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 26 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 27 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build](https://travis-ci.org/infinit/dopenssl.svg?branch=master)](https://travis-ci.org/infinit/dopenssl) [![Code Coverage](https://codecov.io/gh/infinit/dopenssl/branch/master/graph/badge.svg)](https://codecov.io/gh/infinit/dopenssl) 2 | 3 | dOpenSSL 4 | ======== 5 | 6 | The [**dOpenSSL**](http://github.com/infinit/dopenssl) library extends the OpenSSL 7 | Project cryptographic library so as to provide deterministic random generation 8 | functionalities. Basically, dOpenSSL guarantees that should a big number or a 9 | cryptographic key be generated, given a PRNG's state, the result would be always 10 | the same. 11 | 12 | The OpenSSL random generator introduces entropy in many places, making it 13 | unusable in a deterministic way. Thus, some functions have been cloned and 14 | adapted in order to guarantee determinism. 15 | 16 | This product includes software developed by the OpenSSL Project for use 17 | in the OpenSSL Toolkit. (http://www.openssl.org/) 18 | 19 | Sources 20 | ------- 21 | 22 | Retrieve the dOpenSSL sources on Github as follows 23 | 24 | ```Shell 25 | $> git clone git://github.com/infinit/dopenssl.git 26 | ``` 27 | 28 | Build 29 | ----- 30 | 31 | First of all, go to the directory containing the dOpenSSL's sources: 32 | 33 | ```Shell 34 | $> cd dopenssl/ 35 | ``` 36 | 37 | Here you will find all the sources, tests and samples related to dOpenSSL. 38 | Then, go to the build directory related to your machine's operating system and 39 | architecture. All the build directories are located in `_build/`. 40 | 41 | For the purpose of this tutorial, we will assume your machine runs a Linux 42 | 64-bit operating system. 43 | 44 | ```Shell 45 | $> cd _build/linux64/ 46 | ``` 47 | 48 | There are two ways for building dOpenSSL. The first relies on the 49 | [Drake](http://github.com/infinit/drake) build system (which must be installed 50 | on your system) with which dOpenSSL has been developed. The other way 51 | consists in invoking a simple Makefile (generated by Drake). 52 | 53 | ### Drake 54 | 55 | Assuming Drake has been installed on your system and is referenced in the 56 | `PYTHONPATH` environment variable, simply invoke the `//build` rule so as to 57 | compile and generate the dOpenSSL library. 58 | 59 | ```Shell 60 | $> ./drake //build 61 | Compile sources/dopenssl/rand.o 62 | Compile sources/dopenssl/bn.o 63 | Compile sources/dopenssl/rsa.o 64 | Link lib/libdopenssl.a 65 | Link lib/libdopenssl.so 66 | $> 67 | ``` 68 | 69 | Alternatively, one may want to invoke the drake script with a specific python 70 | binary, so as to use the latest python version for instance: 71 | 72 | ```Shell 73 | $> python3.2 ./drake //build 74 | ``` 75 | 76 | At this point, the dOpenSSL library has been built successfully. 77 | 78 | ### Make 79 | 80 | Simply invoke the Makefile's `build` rule as follows: 81 | 82 | ```Shell 83 | $> make build 84 | ``` 85 | 86 | Test 87 | ---- 88 | 89 | Making sure the dOpenSSL library has been properly built and behaves as expected 90 | on your system is important. 91 | 92 | Note that the following assumes your are still in the `_build/linux64/` 93 | directory. 94 | 95 | ### Drake 96 | 97 | Just invoke the `//check` rule which will both compile the tests and run them. 98 | 99 | ```Shell 100 | $> ./drake //check 101 | Compile tests/dopenssl/rsa.o 102 | Compile tests/dopenssl/rand.o 103 | Compile tests/dopenssl/bn.o 104 | Link tests/dopenssl/rsa 105 | Link tests/dopenssl/rand 106 | Link tests/dopenssl/bn 107 | Run tests/dopenssl/rsa 108 | Run tests/dopenssl/rand 109 | Run tests/dopenssl/bn 110 | $> 111 | ``` 112 | 113 | ### Make 114 | 115 | Likewise, invoke the `check` rule so as to run the tests. 116 | 117 | ```Shell 118 | $> make check 119 | ``` 120 | 121 | Install 122 | ------- 123 | 124 | Installing dOpenSSL on your system is as simple as the previous steps. 125 | 126 | ### Drake 127 | 128 | Invoke the `//install` rule so as to copy the library files on your system. 129 | Note that the `--prefix` option can be passed so as to specify the destination 130 | directory. 131 | 132 | The example below install the dOpenSSL library in `$HOME/local/` with the 133 | header files in `$HOME/local/include/` and the library files in 134 | `$HOME/local/lib/`. 135 | 136 | ```Shell 137 | $> ./drake //install --prefix=$HOME/local/ 138 | ``` 139 | 140 | ### Make 141 | 142 | Once again, nothing could be simpler, the `install` rule make it extremely easy 143 | to install the library files: 144 | 145 | ```Shell 146 | $> make install 147 | ``` 148 | 149 | Note that you may need to be `root` in order to install the dOpenSSL library 150 | in one of your system's directories. 151 | 152 | Examples 153 | -------- 154 | 155 | The following source code can be copied and pasted in a test file, say `test.c`. 156 | This sample shows how dOpenSSL can be used to generate cryptographic keys --- 157 | in this case 2048-bit RSA keys --- in a deterministic way i.e based on a given 158 | passphrase. The program therefore assures that, given the same passphrase, the 159 | exact same RSA key will be generated. 160 | 161 | ```C 162 | #include 163 | #include 164 | #include 165 | 166 | #include 167 | #include 168 | 169 | int main(int argc, char **argv) 170 | { 171 | if (argc != 2) 172 | { 173 | printf("usage: %s [passphrase]\n", argv[0]); 174 | return(1); 175 | } 176 | 177 | unsigned int const bits = 2048; 178 | 179 | char const* passphrase = argv[1]; 180 | unsigned int const length = strlen(passphrase); 181 | unsigned int const size = bits / 8; 182 | unsigned int const occurences = size / length + 1; 183 | 184 | unsigned char* seed = malloc(occurences * length + 1); 185 | memset(seed, 0x0, occurences * length + 1); 186 | 187 | /* Concatenate the passphrase so as to create a 256-byte buffer */ 188 | unsigned int i; 189 | for (i = 0; i < occurences; i++) 190 | strncpy(seed + (i * length), passphrase, length); 191 | 192 | /* Initialize the deterministic random generator */ 193 | if (dRAND_init() != 1) 194 | { 195 | printf("[error] unable to initialize the random generator\n"); 196 | return (1); 197 | } 198 | 199 | /* Generate the RSA key */ 200 | RSA* rsa = NULL; 201 | 202 | if ((rsa = dRSA_deduce_privatekey(bits, seed, size)) == NULL) 203 | { 204 | printf("[error] unable to generate the RSA key pair\n"); 205 | return (1); 206 | } 207 | 208 | /* Display the RSA components */ 209 | RSA_print_fp(stdout, rsa, 0); 210 | 211 | /* Clean the resources */ 212 | if (dRAND_clean() != 1) 213 | { 214 | printf("[error] unable to clean the random generator\n"); 215 | return (1); 216 | } 217 | 218 | return (0); 219 | } 220 | ``` 221 | 222 | Assuming the dOpenSSL library has been installed in `$HOME/local/`, the sample 223 | program can be compiled as follows: 224 | 225 | ```Shell 226 | $> gcc -I $HOME/local/include -L $HOME/local/lib -ldopenssl -lcrypto test.c -o test 227 | ``` 228 | 229 | Note that you may need to add the library directory where OpenSSL has been 230 | installed e.g `/usr/lib/`, `/opt/local/lib/` etc. 231 | 232 | ```Shell 233 | $> gcc -I $HOME/local/include -L $HOME/local/lib -L /opt/local/lib -ldopenssl -lcrypto test.c -o test 234 | ``` 235 | 236 | Then, in order to launch the program, you may need to specify your system where 237 | to look for libraries, again assuming dOpenSSL has been installed in 238 | `$HOME/local/`: 239 | 240 | ```Shell 241 | $> export LD_LIBRARY_PATH=$HOME/local/lib:${LD_LIBRARY_PATH} 242 | ``` 243 | 244 | Finally, just launch the sample program by providing a passphrase: 245 | 246 | ```Shell 247 | $> ./test "chiche donne nous tout" 248 | Private-Key: (2048 bit) 249 | modulus: 250 | 00:c2:06:28:58:c4:ee:e8:d0:65:e5:2f:fd:d4:1c: 251 | 86:73:fb:77:ab:cc:ee:50:3e:20:b1:d2:7e:3c:bf: 252 | 20:35:2f:b7:1e:ab:4a:03:d0:9f:c7:8f:46:44:8f: 253 | 03:a4:3c:da:e2:19:f0:fe:41:e2:7b:41:75:76:3a: 254 | b0:d0:de:eb:26:dd:4c:c7:50:d5:33:61:bf:71:8a: 255 | 6e:b2:bb:bf:1b:2e:14:6b:a3:1c:c7:0d:5a:31:67: 256 | 2c:9f:e9:17:56:31:8c:9f:86:93:f7:b3:2e:2c:c0: 257 | 59:24:43:5c:ed:bd:0b:bc:4d:65:33:c7:89:4e:62: 258 | f7:9f:cd:da:5c:f9:e4:c9:b2:9c:43:6f:78:06:32: 259 | e6:f5:07:1e:c0:fa:1e:6d:4b:c8:68:a8:93:a7:53: 260 | e7:11:92:e0:e0:43:6d:11:36:a6:37:18:9b:33:c3: 261 | 8a:75:cf:3a:10:18:67:3c:13:07:6c:a6:6b:f2:6b: 262 | 36:aa:fd:9c:29:5a:38:95:0d:e0:a2:81:07:41:9a: 263 | 17:62:a4:9e:fc:a7:32:1a:3d:79:83:75:fa:73:e8: 264 | 47:e2:ac:08:2e:65:cc:12:a1:ac:59:b1:e8:e1:4d: 265 | 6c:0e:8e:01:02:53:f1:52:04:a3:3f:03:c4:02:0a: 266 | 9f:35:3f:a2:b9:4d:66:31:63:5a:77:3d:28:ab:bb: 267 | 24:6f 268 | publicExponent: 269 | 01:b4:65:67:bf:94:56:af:f4:12:61:6b:73:7e:e8: 270 | 89:5e:95:39:44:ac:7c:85:5c:fe:65:4f:23:1e:b8: 271 | 96:50:3f:bc:27:89:ae:8a:84:4a:d9:07:8a:67:5f: 272 | 20:7f:85:90:45:32:db:0f:28:0b:00:2c:3f:16:d1: 273 | 4c:69:82:df:d5:05:35:8c:ed:2e:69:b9:cc:c2:69: 274 | 50:5b:30:96:b9:51:b5:8d:4e:25:9a:ef:d7:fa:ae: 275 | 65:f2:3b:41:32:19:e3:04:81:1d:a5:ec:d8:d1:04: 276 | ad:e5:af:42:4a:1d:91:88:9c:6e:09:32:43:3a:e9: 277 | d3:83:60:64:b2:54:4c:98:1b 278 | [...] 279 | $> 280 | ``` 281 | 282 | Note that you should get exactly the same output since dOpenSSL guarantees the 283 | result is deterministic. 284 | 285 | Dependencies 286 | ------------ 287 | 288 | The library relies upon the following libraries: 289 | 290 | * [**OpenSSL**](http://www.openssl.org) which provides the fundamental cryptographic operations. 291 | 292 | Internals 293 | --------- 294 | 295 | The library is composed of a three components, all required for ensuring the 296 | determinism of the cryptography key generation mechanism. 297 | 298 | First, a deterministic random implementation is provided, referred to as dRAND. 299 | 300 | Although this implementation is deterministic, determinism must also be assured 301 | at the BIGNUM level because some of the functions introduce entroy, the ones 302 | related to `BN_generate_prime_ex()` for instance. 303 | 304 | Finally a set of functions for deducing a private/public key from a PRNG state 305 | in a deterministic way is provided for every asymmetric cryptosystem, such as 306 | RSA. 307 | 308 | In other words, some of the OpenSSL library's functions have been slightly 309 | modified so as to remove the operations destined at adding entropy, especially 310 | the ones based on uninitialized variables. 311 | 312 | The reader interested in looking at these slight modifications can look around 313 | for "PATCHED". 314 | 315 | Maintainers 316 | ----------- 317 | 318 | * Website: http://infinit.sh 319 | * Email: contact@infinit.sh 320 | -------------------------------------------------------------------------------- /_build/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:17.10 2 | 3 | RUN apt-get update 4 | RUN apt-get install -y openssl 5 | 6 | WORKDIR /app 7 | 8 | COPY linux64/src/sample /app/bin/sample 9 | COPY linux64/lib /app/lib 10 | 11 | ENTRYPOINT ["/app/bin/sample"] 12 | -------------------------------------------------------------------------------- /_build/linux64/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | AR=ar 3 | RANLIB=ranlib 4 | 5 | OPENSSL_INCLUDE_DIRECTORY=/usr/local/opt/openssl/include 6 | OPENSSL_LIBRARY_DIRECTORY=/usr/local/opt/openssl/lib 7 | 8 | all: build tests check tests/dopenssl/bn.status tests/dopenssl/rand.status tests/dopenssl/rsa.status 9 | 10 | build: lib/libdopenssl.a lib/libdopenssl.so 11 | 12 | lib/libdopenssl.so: src/dopenssl/rand.o src/dopenssl/bn.o src/dopenssl/rsa.o 13 | @mkdir -p lib 14 | ${CC} -Wall -fprofile-arcs -ftest-coverage -fPIC -L lib -L ${OPENSSL_LIBRARY_DIRECTORY} '-Wl,-rpath,$$ORIGIN' src/dopenssl/bn.o src/dopenssl/rand.o src/dopenssl/rsa.o -shared -o lib/libdopenssl.so -lcrypto -lssl 15 | 16 | lib/libdopenssl.a: src/dopenssl/rand.o src/dopenssl/bn.o src/dopenssl/rsa.o 17 | @mkdir -p lib 18 | ${AR} crs lib/libdopenssl.a src/dopenssl/bn.o src/dopenssl/rand.o src/dopenssl/rsa.o 19 | ${RANLIB} lib/libdopenssl.a 20 | 21 | src/dopenssl/bn.o: ../../src/dopenssl/bn.c 22 | @mkdir -p src/dopenssl 23 | ${CC} -Wall -fprofile-arcs -ftest-coverage -fPIC -isystem . -isystem ${OPENSSL_INCLUDE_DIRECTORY} -I ../../src -I src -O2 -fPIC -c ../../src/dopenssl/bn.c -o src/dopenssl/bn.o 24 | 25 | src/dopenssl/rand.o: ../../src/dopenssl/rand.c 26 | @mkdir -p src/dopenssl 27 | ${CC} -Wall -fprofile-arcs -ftest-coverage -fPIC -isystem . -isystem ${OPENSSL_INCLUDE_DIRECTORY} -I ../../src -I src -O2 -fPIC -c ../../src/dopenssl/rand.c -o src/dopenssl/rand.o 28 | 29 | src/dopenssl/rsa.o: ../../src/dopenssl/rsa.c 30 | @mkdir -p src/dopenssl 31 | ${CC} -Wall -fprofile-arcs -ftest-coverage -fPIC -isystem . -isystem ${OPENSSL_INCLUDE_DIRECTORY} -I ../../src -I src -O2 -fPIC -c ../../src/dopenssl/rsa.c -o src/dopenssl/rsa.o 32 | 33 | tests: tests/dopenssl/bn tests/dopenssl/rand tests/dopenssl/rsa 34 | 35 | check: tests/dopenssl/bn.status tests/dopenssl/rand.status tests/dopenssl/rsa.status 36 | 37 | tests/dopenssl/bn: tests/dopenssl/bn.o lib/libdopenssl.so 38 | @mkdir -p tests/dopenssl 39 | ${CC} -L lib -L ${OPENSSL_LIBRARY_DIRECTORY} -Wl,-rpath-link,lib '-Wl,-rpath,$$ORIGIN' '-Wl,-rpath,$$ORIGIN/../../lib' -fprofile-arcs -lgcov --coverage tests/dopenssl/bn.o -o tests/dopenssl/bn -lcrypto -ldopenssl -lssl 40 | 41 | tests/dopenssl/rand: tests/dopenssl/rand.o lib/libdopenssl.so 42 | @mkdir -p tests/dopenssl 43 | ${CC} -L lib -L ${OPENSSL_LIBRARY_DIRECTORY} -Wl,-rpath-link,lib '-Wl,-rpath,$$ORIGIN' '-Wl,-rpath,$$ORIGIN/../../lib' -fprofile-arcs -lgcov --coverage tests/dopenssl/rand.o -o tests/dopenssl/rand -lcrypto -ldopenssl -lssl 44 | 45 | tests/dopenssl/rsa: tests/dopenssl/rsa.o lib/libdopenssl.so 46 | @mkdir -p tests/dopenssl 47 | ${CC} -L lib -L ${OPENSSL_LIBRARY_DIRECTORY} -Wl,-rpath-link,lib '-Wl,-rpath,$$ORIGIN' '-Wl,-rpath,$$ORIGIN/../../lib' -fprofile-arcs -lgcov --coverage tests/dopenssl/rsa.o -o tests/dopenssl/rsa -lcrypto -ldopenssl -lssl 48 | 49 | tests/dopenssl/bn.o: ../../tests/dopenssl/bn.c 50 | @mkdir -p tests/dopenssl 51 | ${CC} -Wall -fprofile-arcs -ftest-coverage -fPIC -isystem . -isystem ${OPENSSL_INCLUDE_DIRECTORY} -I ../../src -I src -O2 -c ../../tests/dopenssl/bn.c -o tests/dopenssl/bn.o 52 | 53 | tests/dopenssl/rand.o: ../../tests/dopenssl/rand.c 54 | @mkdir -p tests/dopenssl 55 | ${CC} -Wall -fprofile-arcs -ftest-coverage -fPIC -isystem . -isystem ${OPENSSL_INCLUDE_DIRECTORY} -I ../../src -I src -O2 -c ../../tests/dopenssl/rand.c -o tests/dopenssl/rand.o 56 | 57 | tests/dopenssl/rsa.o: ../../tests/dopenssl/rsa.c 58 | @mkdir -p tests/dopenssl 59 | ${CC} -Wall -fprofile-arcs -ftest-coverage -fPIC -isystem . -isystem ${OPENSSL_INCLUDE_DIRECTORY} -I ../../src -I src -O2 -c ../../tests/dopenssl/rsa.c -o tests/dopenssl/rsa.o 60 | 61 | tests/dopenssl/rsa.status: tests/dopenssl/rsa lib/libdopenssl.so 62 | @mkdir -p tests/dopenssl 63 | tests/dopenssl/rsa 64 | 65 | tests/dopenssl/rand.status: tests/dopenssl/rand lib/libdopenssl.so 66 | @mkdir -p tests/dopenssl 67 | tests/dopenssl/rand 68 | 69 | tests/dopenssl/bn.status: tests/dopenssl/bn lib/libdopenssl.so 70 | @mkdir -p tests/dopenssl 71 | tests/dopenssl/bn 72 | 73 | sample: 74 | ${CC} -Wall -fprofile-arcs -ftest-coverage -fPIC -isystem . -isystem ${OPENSSL_INCLUDE_DIRECTORY} -I ../../src -I src -O2 -c ../../src/sample.c -o src/sample.o 75 | ${CC} -L lib -L ${OPENSSL_LIBRARY_DIRECTORY} -Wl,-rpath-link,lib '-Wl,-rpath,$$ORIGIN' '-Wl,-rpath,$$ORIGIN/../lib' -fprofile-arcs -lgcov --coverage src/sample.o -o src/sample -lcrypto -ldopenssl -lssl 76 | -------------------------------------------------------------------------------- /_build/linux64/drake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | import sys 5 | root = os.path.dirname(__file__) 6 | drake = os.path.abspath(os.path.join(root, '../../../../../drake/src')) 7 | sys.path.insert(0, drake) 8 | 9 | import resource 10 | resource.setrlimit(resource.RLIMIT_NOFILE, (500, -1)) 11 | 12 | import drake 13 | import drake.cxx 14 | 15 | with drake.Drake('../..') as d: 16 | c_compiler = os.getenv('CC', 'gcc') 17 | cxx_compiler = os.getenv('CXX', 'g++') 18 | 19 | cxx_toolkit = drake.cxx.GccToolkit(compiler_c = c_compiler, compiler = cxx_compiler) 20 | cxx_config = drake.cxx.Config() 21 | 22 | cxx_config.flag('-fPIC') 23 | cxx_config.flag('-Wall') 24 | cxx_config.flag('-coverage') 25 | cxx_config.enable_debug_symbols(False) 26 | cxx_config.enable_optimization(True) 27 | 28 | d.run(cxx_toolkit, 29 | cxx_config, 30 | ) 31 | -------------------------------------------------------------------------------- /_build/macosx64/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | AR=ar 3 | RANLIB=ranlib 4 | 5 | OPENSSL_INCLUDE_DIRECTORY=/usr/local/opt/openssl/include 6 | OPENSSL_LIBRARY_DIRECTORY=/usr/local/opt/openssl/lib 7 | 8 | all: build tests check tests/dopenssl/bn.status tests/dopenssl/rand.status tests/dopenssl/rsa.status 9 | 10 | build: lib/libdopenssl.a lib/libdopenssl.dylib 11 | 12 | lib/libdopenssl.dylib: src/dopenssl/rand.o src/dopenssl/bn.o src/dopenssl/rsa.o 13 | @mkdir -p lib 14 | ${CC} -Wall -coverage -fPIC -L lib -L ${OPENSSL_LIBRARY_DIRECTORY} -Wl,-rpath,@loader_path -undefined dynamic_lookup -Wl,-install_name,@rpath/libdopenssl.dylib -Wl,-headerpad_max_install_names src/dopenssl/bn.o src/dopenssl/rand.o src/dopenssl/rsa.o -shared -o lib/libdopenssl.dylib -lssl -lcrypto 15 | 16 | lib/libdopenssl.a: src/dopenssl/rand.o src/dopenssl/bn.o src/dopenssl/rsa.o 17 | @mkdir -p lib 18 | ${AR} crs lib/libdopenssl.a src/dopenssl/bn.o src/dopenssl/rand.o src/dopenssl/rsa.o 19 | ${RANLIB} lib/libdopenssl.a 20 | 21 | src/dopenssl/bn.o: ../../src/dopenssl/bn.c 22 | @mkdir -p src/dopenssl 23 | ${CC} -Wall -coverage -fPIC -isystem ${OPENSSL_INCLUDE_DIRECTORY} -isystem . -I ../../src -I src -O2 -fPIC -c ../../src/dopenssl/bn.c -o src/dopenssl/bn.o 24 | 25 | src/dopenssl/rand.o: ../../src/dopenssl/rand.c 26 | @mkdir -p src/dopenssl 27 | ${CC} -Wall -coverage -fPIC -isystem ${OPENSSL_INCLUDE_DIRECTORY} -isystem . -I ../../src -I src -O2 -fPIC -c ../../src/dopenssl/rand.c -o src/dopenssl/rand.o 28 | 29 | src/dopenssl/rsa.o: ../../src/dopenssl/rsa.c 30 | @mkdir -p src/dopenssl 31 | ${CC} -Wall -coverage -fPIC -isystem ${OPENSSL_INCLUDE_DIRECTORY} -isystem . -I ../../src -I src -O2 -fPIC -c ../../src/dopenssl/rsa.c -o src/dopenssl/rsa.o 32 | 33 | tests: tests/dopenssl/bn tests/dopenssl/rand tests/dopenssl/rsa 34 | 35 | check: tests/dopenssl/bn.status tests/dopenssl/rand.status tests/dopenssl/rsa.status 36 | 37 | tests/dopenssl/bn: tests/dopenssl/bn.o lib/libdopenssl.dylib 38 | @mkdir -p tests/dopenssl 39 | ${CC} -L lib -L ${OPENSSL_LIBRARY_DIRECTORY} -Wl,-rpath,@loader_path -Wl,-rpath,@loader_path/../../lib -undefined dynamic_lookup tests/dopenssl/bn.o -o tests/dopenssl/bn -lssl -lcrypto -ldopenssl 40 | 41 | tests/dopenssl/rand: tests/dopenssl/rand.o lib/libdopenssl.dylib 42 | @mkdir -p tests/dopenssl 43 | ${CC} -L lib -L ${OPENSSL_LIBRARY_DIRECTORY} -Wl,-rpath,@loader_path -Wl,-rpath,@loader_path/../../lib -undefined dynamic_lookup tests/dopenssl/rand.o -o tests/dopenssl/rand -lssl -lcrypto -ldopenssl 44 | 45 | tests/dopenssl/rsa: lib/libdopenssl.dylib tests/dopenssl/rsa.o 46 | @mkdir -p tests/dopenssl 47 | ${CC} -L lib -L ${OPENSSL_LIBRARY_DIRECTORY} -Wl,-rpath,@loader_path -Wl,-rpath,@loader_path/../../lib -undefined dynamic_lookup tests/dopenssl/rsa.o -o tests/dopenssl/rsa -lssl -lcrypto -ldopenssl 48 | 49 | tests/dopenssl/bn.o: ../../tests/dopenssl/bn.c 50 | @mkdir -p tests/dopenssl 51 | ${CC} -Wall -coverage -fPIC -isystem ${OPENSSL_INCLUDE_DIRECTORY} -isystem . -I ../../src -I src -O2 -c ../../tests/dopenssl/bn.c -o tests/dopenssl/bn.o 52 | 53 | tests/dopenssl/rand.o: ../../tests/dopenssl/rand.c 54 | @mkdir -p tests/dopenssl 55 | ${CC} -Wall -coverage -fPIC -isystem ${OPENSSL_INCLUDE_DIRECTORY} -isystem . -I ../../src -I src -O2 -c ../../tests/dopenssl/rand.c -o tests/dopenssl/rand.o 56 | 57 | tests/dopenssl/rsa.o: ../../tests/dopenssl/rsa.c 58 | @mkdir -p tests/dopenssl 59 | ${CC} -Wall -coverage -fPIC -isystem ${OPENSSL_INCLUDE_DIRECTORY} -isystem . -I ../../src -I src -O2 -c ../../tests/dopenssl/rsa.c -o tests/dopenssl/rsa.o 60 | 61 | tests/dopenssl/rsa.status: tests/dopenssl/rsa lib/libdopenssl.dylib 62 | @mkdir -p tests/dopenssl 63 | tests/dopenssl/rsa 64 | 65 | tests/dopenssl/rand.status: tests/dopenssl/rand lib/libdopenssl.dylib 66 | @mkdir -p tests/dopenssl 67 | tests/dopenssl/rand 68 | 69 | tests/dopenssl/bn.status: tests/dopenssl/bn lib/libdopenssl.dylib 70 | @mkdir -p tests/dopenssl 71 | tests/dopenssl/bn 72 | 73 | sample: 74 | ${CC} -Wall -coverage -fPIC -isystem ${OPENSSL_INCLUDE_DIRECTORY} -isystem . -I ../../src -I src -O2 -c ../../src/sample.c -o src/sample.o 75 | ${CC} -L lib -L ${OPENSSL_LIBRARY_DIRECTORY} -Wl,-rpath,@loader_path -Wl,-rpath,@loader_path/../lib -undefined dynamic_lookup src/sample.o -o src/sample -lssl -lcrypto -ldopenssl 76 | -------------------------------------------------------------------------------- /_build/macosx64/drake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | import sys 5 | root = os.path.dirname(__file__) 6 | drake = os.path.abspath(os.path.join(root, '../../../../../drake/src')) 7 | sys.path.insert(0, drake) 8 | 9 | import resource 10 | resource.setrlimit(resource.RLIMIT_NOFILE, (500, -1)) 11 | 12 | import drake 13 | import drake.cxx 14 | 15 | with drake.Drake('../..') as d: 16 | c_compiler = os.getenv('CC', 'clang') 17 | cxx_compiler = os.getenv('CXX', 'clang++') 18 | 19 | cxx_toolkit = drake.cxx.GccToolkit(compiler_c = c_compiler, compiler = cxx_compiler) 20 | os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.7' # ensure that build is compatible with 10.7 21 | 22 | cxx_config = drake.cxx.Config() 23 | 24 | cxx_config.flag('-fPIC') 25 | cxx_config.flag('-Wall') 26 | cxx_config.flag('-coverage') 27 | cxx_config.enable_debug_symbols(False) 28 | cxx_config.enable_optimization(True) 29 | 30 | d.run(cxx_toolkit, 31 | cxx_config, 32 | openssl_config = '/usr/local/opt/openssl' 33 | ) 34 | -------------------------------------------------------------------------------- /drakefile: -------------------------------------------------------------------------------- 1 | import drake 2 | import drake.cxx 3 | 4 | config = None 5 | lib_static = None 6 | lib_dynamic = None 7 | 8 | rule_build = None 9 | rule_check = None 10 | rule_install = None 11 | rule_tests = None 12 | 13 | def configure(cxx_toolkit = None, 14 | cxx_config = None, 15 | openssl_config = None, 16 | openssl_lib_crypto = None, 17 | openssl_lib_ssl = None, 18 | prefix = '/usr'): 19 | 20 | global config, lib_static, lib_dynamic, rule_build, rule_check, rule_install 21 | 22 | # Toolkit 23 | cxx_toolkit = cxx_toolkit or drake.cxx.Toolkit() 24 | 25 | # Global Configuration 26 | config = drake.cxx.Config(cxx_config) 27 | config.add_local_include_path('src') 28 | 29 | # Local Configuration 30 | cxx_config = drake.cxx.Config(config) 31 | 32 | # Sources 33 | sources = drake.nodes( 34 | 'src/dopenssl/all.h', 35 | 'src/dopenssl/bn.c', 36 | 'src/dopenssl/bn.h', 37 | 'src/dopenssl/rand.c', 38 | 'src/dopenssl/rand.h', 39 | 'src/dopenssl/rsa.c', 40 | 'src/dopenssl/rsa.h', 41 | ) 42 | 43 | # Tests 44 | tests = ['bn', 45 | 'rand', 46 | 'rsa'] 47 | 48 | openssl_libs = [] 49 | if openssl_lib_crypto and openssl_lib_ssl: 50 | cxx_config += openssl_config 51 | openssl_libs = drake.copy([openssl_lib_crypto, openssl_lib_ssl], 52 | 'lib', strip_prefix = True) 53 | else: 54 | cxx_config += openssl_config 55 | openssl_config = drake.cxx.find_library('openssl/opensslconf.h', prefix = openssl_config) 56 | cxx_config.lib('crypto') 57 | cxx_config.lib('ssl') 58 | 59 | cxx_config.lib_path_runtime('.') 60 | 61 | lib_static = drake.cxx.StaticLib('lib/dopenssl', 62 | sources + openssl_libs, 63 | cxx_toolkit, cxx_config) 64 | lib_dynamic = drake.cxx.DynLib('lib/dopenssl', 65 | sources + openssl_libs, 66 | cxx_toolkit, cxx_config) 67 | 68 | # Build 69 | rule_build = drake.Rule('build') 70 | rule_build << lib_static 71 | rule_build << lib_dynamic 72 | 73 | # Tests 74 | global rule_check, rule_tests 75 | 76 | rule_tests = drake.Rule('tests') 77 | rule_check = drake.Rule('check') 78 | 79 | tests_cxx_config = drake.cxx.Config(cxx_config) 80 | 81 | for test in tests: 82 | config_test = drake.cxx.Config(tests_cxx_config) 83 | config_test.lib_path_runtime('%s../../lib' % ('../' * test.count('/'))) 84 | path = drake.Path('tests/dopenssl/%s.c' % test) 85 | bin_path = drake.Path('tests/dopenssl/%s' % test) 86 | bin = drake.cxx.Executable(bin_path, 87 | drake.nodes(path) + 88 | [lib_dynamic] + openssl_libs, 89 | cxx_toolkit, config_test) 90 | rule_tests << bin 91 | runner = drake.Runner(bin) 92 | rule_check << runner.status 93 | 94 | # Install 95 | rule_install = drake.Rule('install') 96 | prefix = drake.Path(prefix) 97 | rule_install << drake.install(lib_dynamic, prefix) 98 | rule_install << drake.install(lib_static, prefix) 99 | rule_install << drake.install(list(filter(lambda n: isinstance(n, drake.cxx.Header), sources)), prefix / 'include', 'src') 100 | -------------------------------------------------------------------------------- /src/dopenssl/all.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013, infinit.io 3 | * 4 | * This software is provided "as is" without warranty of any kind, 5 | * either expressed or implied, including but not limited to the 6 | * implied warranties of fitness for a particular purpose. 7 | * 8 | * See the LICENSE file for more information on the terms and 9 | * conditions. 10 | */ 11 | 12 | #ifndef DOPENSSL_ALL_H 13 | # define DOPENSSL_ALL_H 14 | 15 | # include 16 | # include 17 | # include 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /src/dopenssl/all.hh: -------------------------------------------------------------------------------- 1 | extern "C" 2 | { 3 | # include 4 | } 5 | -------------------------------------------------------------------------------- /src/dopenssl/bn.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013, infinit.io 3 | * 4 | * This software is provided "as is" without warranty of any kind, 5 | * either expressed or implied, including but not limited to the 6 | * implied warranties of fitness for a particular purpose. 7 | * 8 | * See the LICENSE file for more information on the terms and 9 | * conditions. 10 | */ 11 | 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | /* 26 | * ---------- Original Functionalities ---------------------------------------- 27 | * 28 | * Based on the following OpenSSL files: 29 | * 30 | * crypto/bn/bn_prime.h 31 | * crypto/bn/bn_prime.c 32 | * crypto/bn/bn_rand.c 33 | */ 34 | 35 | #ifndef EIGHT_BIT 36 | #define NUMPRIMES 2048 37 | typedef unsigned short prime_t; 38 | #else 39 | #define NUMPRIMES 54 40 | typedef unsigned char prime_t; 41 | #endif 42 | static const prime_t primes[NUMPRIMES]= 43 | { 44 | 2, 3, 5, 7, 11, 13, 17, 19, 45 | 23, 29, 31, 37, 41, 43, 47, 53, 46 | 59, 61, 67, 71, 73, 79, 83, 89, 47 | 97, 101, 103, 107, 109, 113, 127, 131, 48 | 137, 139, 149, 151, 157, 163, 167, 173, 49 | 179, 181, 191, 193, 197, 199, 211, 223, 50 | 227, 229, 233, 239, 241, 251, 51 | #ifndef EIGHT_BIT 52 | 257, 263, 53 | 269, 271, 277, 281, 283, 293, 307, 311, 54 | 313, 317, 331, 337, 347, 349, 353, 359, 55 | 367, 373, 379, 383, 389, 397, 401, 409, 56 | 419, 421, 431, 433, 439, 443, 449, 457, 57 | 461, 463, 467, 479, 487, 491, 499, 503, 58 | 509, 521, 523, 541, 547, 557, 563, 569, 59 | 571, 577, 587, 593, 599, 601, 607, 613, 60 | 617, 619, 631, 641, 643, 647, 653, 659, 61 | 661, 673, 677, 683, 691, 701, 709, 719, 62 | 727, 733, 739, 743, 751, 757, 761, 769, 63 | 773, 787, 797, 809, 811, 821, 823, 827, 64 | 829, 839, 853, 857, 859, 863, 877, 881, 65 | 883, 887, 907, 911, 919, 929, 937, 941, 66 | 947, 953, 967, 971, 977, 983, 991, 997, 67 | 1009,1013,1019,1021,1031,1033,1039,1049, 68 | 1051,1061,1063,1069,1087,1091,1093,1097, 69 | 1103,1109,1117,1123,1129,1151,1153,1163, 70 | 1171,1181,1187,1193,1201,1213,1217,1223, 71 | 1229,1231,1237,1249,1259,1277,1279,1283, 72 | 1289,1291,1297,1301,1303,1307,1319,1321, 73 | 1327,1361,1367,1373,1381,1399,1409,1423, 74 | 1427,1429,1433,1439,1447,1451,1453,1459, 75 | 1471,1481,1483,1487,1489,1493,1499,1511, 76 | 1523,1531,1543,1549,1553,1559,1567,1571, 77 | 1579,1583,1597,1601,1607,1609,1613,1619, 78 | 1621,1627,1637,1657,1663,1667,1669,1693, 79 | 1697,1699,1709,1721,1723,1733,1741,1747, 80 | 1753,1759,1777,1783,1787,1789,1801,1811, 81 | 1823,1831,1847,1861,1867,1871,1873,1877, 82 | 1879,1889,1901,1907,1913,1931,1933,1949, 83 | 1951,1973,1979,1987,1993,1997,1999,2003, 84 | 2011,2017,2027,2029,2039,2053,2063,2069, 85 | 2081,2083,2087,2089,2099,2111,2113,2129, 86 | 2131,2137,2141,2143,2153,2161,2179,2203, 87 | 2207,2213,2221,2237,2239,2243,2251,2267, 88 | 2269,2273,2281,2287,2293,2297,2309,2311, 89 | 2333,2339,2341,2347,2351,2357,2371,2377, 90 | 2381,2383,2389,2393,2399,2411,2417,2423, 91 | 2437,2441,2447,2459,2467,2473,2477,2503, 92 | 2521,2531,2539,2543,2549,2551,2557,2579, 93 | 2591,2593,2609,2617,2621,2633,2647,2657, 94 | 2659,2663,2671,2677,2683,2687,2689,2693, 95 | 2699,2707,2711,2713,2719,2729,2731,2741, 96 | 2749,2753,2767,2777,2789,2791,2797,2801, 97 | 2803,2819,2833,2837,2843,2851,2857,2861, 98 | 2879,2887,2897,2903,2909,2917,2927,2939, 99 | 2953,2957,2963,2969,2971,2999,3001,3011, 100 | 3019,3023,3037,3041,3049,3061,3067,3079, 101 | 3083,3089,3109,3119,3121,3137,3163,3167, 102 | 3169,3181,3187,3191,3203,3209,3217,3221, 103 | 3229,3251,3253,3257,3259,3271,3299,3301, 104 | 3307,3313,3319,3323,3329,3331,3343,3347, 105 | 3359,3361,3371,3373,3389,3391,3407,3413, 106 | 3433,3449,3457,3461,3463,3467,3469,3491, 107 | 3499,3511,3517,3527,3529,3533,3539,3541, 108 | 3547,3557,3559,3571,3581,3583,3593,3607, 109 | 3613,3617,3623,3631,3637,3643,3659,3671, 110 | 3673,3677,3691,3697,3701,3709,3719,3727, 111 | 3733,3739,3761,3767,3769,3779,3793,3797, 112 | 3803,3821,3823,3833,3847,3851,3853,3863, 113 | 3877,3881,3889,3907,3911,3917,3919,3923, 114 | 3929,3931,3943,3947,3967,3989,4001,4003, 115 | 4007,4013,4019,4021,4027,4049,4051,4057, 116 | 4073,4079,4091,4093,4099,4111,4127,4129, 117 | 4133,4139,4153,4157,4159,4177,4201,4211, 118 | 4217,4219,4229,4231,4241,4243,4253,4259, 119 | 4261,4271,4273,4283,4289,4297,4327,4337, 120 | 4339,4349,4357,4363,4373,4391,4397,4409, 121 | 4421,4423,4441,4447,4451,4457,4463,4481, 122 | 4483,4493,4507,4513,4517,4519,4523,4547, 123 | 4549,4561,4567,4583,4591,4597,4603,4621, 124 | 4637,4639,4643,4649,4651,4657,4663,4673, 125 | 4679,4691,4703,4721,4723,4729,4733,4751, 126 | 4759,4783,4787,4789,4793,4799,4801,4813, 127 | 4817,4831,4861,4871,4877,4889,4903,4909, 128 | 4919,4931,4933,4937,4943,4951,4957,4967, 129 | 4969,4973,4987,4993,4999,5003,5009,5011, 130 | 5021,5023,5039,5051,5059,5077,5081,5087, 131 | 5099,5101,5107,5113,5119,5147,5153,5167, 132 | 5171,5179,5189,5197,5209,5227,5231,5233, 133 | 5237,5261,5273,5279,5281,5297,5303,5309, 134 | 5323,5333,5347,5351,5381,5387,5393,5399, 135 | 5407,5413,5417,5419,5431,5437,5441,5443, 136 | 5449,5471,5477,5479,5483,5501,5503,5507, 137 | 5519,5521,5527,5531,5557,5563,5569,5573, 138 | 5581,5591,5623,5639,5641,5647,5651,5653, 139 | 5657,5659,5669,5683,5689,5693,5701,5711, 140 | 5717,5737,5741,5743,5749,5779,5783,5791, 141 | 5801,5807,5813,5821,5827,5839,5843,5849, 142 | 5851,5857,5861,5867,5869,5879,5881,5897, 143 | 5903,5923,5927,5939,5953,5981,5987,6007, 144 | 6011,6029,6037,6043,6047,6053,6067,6073, 145 | 6079,6089,6091,6101,6113,6121,6131,6133, 146 | 6143,6151,6163,6173,6197,6199,6203,6211, 147 | 6217,6221,6229,6247,6257,6263,6269,6271, 148 | 6277,6287,6299,6301,6311,6317,6323,6329, 149 | 6337,6343,6353,6359,6361,6367,6373,6379, 150 | 6389,6397,6421,6427,6449,6451,6469,6473, 151 | 6481,6491,6521,6529,6547,6551,6553,6563, 152 | 6569,6571,6577,6581,6599,6607,6619,6637, 153 | 6653,6659,6661,6673,6679,6689,6691,6701, 154 | 6703,6709,6719,6733,6737,6761,6763,6779, 155 | 6781,6791,6793,6803,6823,6827,6829,6833, 156 | 6841,6857,6863,6869,6871,6883,6899,6907, 157 | 6911,6917,6947,6949,6959,6961,6967,6971, 158 | 6977,6983,6991,6997,7001,7013,7019,7027, 159 | 7039,7043,7057,7069,7079,7103,7109,7121, 160 | 7127,7129,7151,7159,7177,7187,7193,7207, 161 | 7211,7213,7219,7229,7237,7243,7247,7253, 162 | 7283,7297,7307,7309,7321,7331,7333,7349, 163 | 7351,7369,7393,7411,7417,7433,7451,7457, 164 | 7459,7477,7481,7487,7489,7499,7507,7517, 165 | 7523,7529,7537,7541,7547,7549,7559,7561, 166 | 7573,7577,7583,7589,7591,7603,7607,7621, 167 | 7639,7643,7649,7669,7673,7681,7687,7691, 168 | 7699,7703,7717,7723,7727,7741,7753,7757, 169 | 7759,7789,7793,7817,7823,7829,7841,7853, 170 | 7867,7873,7877,7879,7883,7901,7907,7919, 171 | 7927,7933,7937,7949,7951,7963,7993,8009, 172 | 8011,8017,8039,8053,8059,8069,8081,8087, 173 | 8089,8093,8101,8111,8117,8123,8147,8161, 174 | 8167,8171,8179,8191,8209,8219,8221,8231, 175 | 8233,8237,8243,8263,8269,8273,8287,8291, 176 | 8293,8297,8311,8317,8329,8353,8363,8369, 177 | 8377,8387,8389,8419,8423,8429,8431,8443, 178 | 8447,8461,8467,8501,8513,8521,8527,8537, 179 | 8539,8543,8563,8573,8581,8597,8599,8609, 180 | 8623,8627,8629,8641,8647,8663,8669,8677, 181 | 8681,8689,8693,8699,8707,8713,8719,8731, 182 | 8737,8741,8747,8753,8761,8779,8783,8803, 183 | 8807,8819,8821,8831,8837,8839,8849,8861, 184 | 8863,8867,8887,8893,8923,8929,8933,8941, 185 | 8951,8963,8969,8971,8999,9001,9007,9011, 186 | 9013,9029,9041,9043,9049,9059,9067,9091, 187 | 9103,9109,9127,9133,9137,9151,9157,9161, 188 | 9173,9181,9187,9199,9203,9209,9221,9227, 189 | 9239,9241,9257,9277,9281,9283,9293,9311, 190 | 9319,9323,9337,9341,9343,9349,9371,9377, 191 | 9391,9397,9403,9413,9419,9421,9431,9433, 192 | 9437,9439,9461,9463,9467,9473,9479,9491, 193 | 9497,9511,9521,9533,9539,9547,9551,9587, 194 | 9601,9613,9619,9623,9629,9631,9643,9649, 195 | 9661,9677,9679,9689,9697,9719,9721,9733, 196 | 9739,9743,9749,9767,9769,9781,9787,9791, 197 | 9803,9811,9817,9829,9833,9839,9851,9857, 198 | 9859,9871,9883,9887,9901,9907,9923,9929, 199 | 9931,9941,9949,9967,9973,10007,10009,10037, 200 | 10039,10061,10067,10069,10079,10091,10093,10099, 201 | 10103,10111,10133,10139,10141,10151,10159,10163, 202 | 10169,10177,10181,10193,10211,10223,10243,10247, 203 | 10253,10259,10267,10271,10273,10289,10301,10303, 204 | 10313,10321,10331,10333,10337,10343,10357,10369, 205 | 10391,10399,10427,10429,10433,10453,10457,10459, 206 | 10463,10477,10487,10499,10501,10513,10529,10531, 207 | 10559,10567,10589,10597,10601,10607,10613,10627, 208 | 10631,10639,10651,10657,10663,10667,10687,10691, 209 | 10709,10711,10723,10729,10733,10739,10753,10771, 210 | 10781,10789,10799,10831,10837,10847,10853,10859, 211 | 10861,10867,10883,10889,10891,10903,10909,10937, 212 | 10939,10949,10957,10973,10979,10987,10993,11003, 213 | 11027,11047,11057,11059,11069,11071,11083,11087, 214 | 11093,11113,11117,11119,11131,11149,11159,11161, 215 | 11171,11173,11177,11197,11213,11239,11243,11251, 216 | 11257,11261,11273,11279,11287,11299,11311,11317, 217 | 11321,11329,11351,11353,11369,11383,11393,11399, 218 | 11411,11423,11437,11443,11447,11467,11471,11483, 219 | 11489,11491,11497,11503,11519,11527,11549,11551, 220 | 11579,11587,11593,11597,11617,11621,11633,11657, 221 | 11677,11681,11689,11699,11701,11717,11719,11731, 222 | 11743,11777,11779,11783,11789,11801,11807,11813, 223 | 11821,11827,11831,11833,11839,11863,11867,11887, 224 | 11897,11903,11909,11923,11927,11933,11939,11941, 225 | 11953,11959,11969,11971,11981,11987,12007,12011, 226 | 12037,12041,12043,12049,12071,12073,12097,12101, 227 | 12107,12109,12113,12119,12143,12149,12157,12161, 228 | 12163,12197,12203,12211,12227,12239,12241,12251, 229 | 12253,12263,12269,12277,12281,12289,12301,12323, 230 | 12329,12343,12347,12373,12377,12379,12391,12401, 231 | 12409,12413,12421,12433,12437,12451,12457,12473, 232 | 12479,12487,12491,12497,12503,12511,12517,12527, 233 | 12539,12541,12547,12553,12569,12577,12583,12589, 234 | 12601,12611,12613,12619,12637,12641,12647,12653, 235 | 12659,12671,12689,12697,12703,12713,12721,12739, 236 | 12743,12757,12763,12781,12791,12799,12809,12821, 237 | 12823,12829,12841,12853,12889,12893,12899,12907, 238 | 12911,12917,12919,12923,12941,12953,12959,12967, 239 | 12973,12979,12983,13001,13003,13007,13009,13033, 240 | 13037,13043,13049,13063,13093,13099,13103,13109, 241 | 13121,13127,13147,13151,13159,13163,13171,13177, 242 | 13183,13187,13217,13219,13229,13241,13249,13259, 243 | 13267,13291,13297,13309,13313,13327,13331,13337, 244 | 13339,13367,13381,13397,13399,13411,13417,13421, 245 | 13441,13451,13457,13463,13469,13477,13487,13499, 246 | 13513,13523,13537,13553,13567,13577,13591,13597, 247 | 13613,13619,13627,13633,13649,13669,13679,13681, 248 | 13687,13691,13693,13697,13709,13711,13721,13723, 249 | 13729,13751,13757,13759,13763,13781,13789,13799, 250 | 13807,13829,13831,13841,13859,13873,13877,13879, 251 | 13883,13901,13903,13907,13913,13921,13931,13933, 252 | 13963,13967,13997,13999,14009,14011,14029,14033, 253 | 14051,14057,14071,14081,14083,14087,14107,14143, 254 | 14149,14153,14159,14173,14177,14197,14207,14221, 255 | 14243,14249,14251,14281,14293,14303,14321,14323, 256 | 14327,14341,14347,14369,14387,14389,14401,14407, 257 | 14411,14419,14423,14431,14437,14447,14449,14461, 258 | 14479,14489,14503,14519,14533,14537,14543,14549, 259 | 14551,14557,14561,14563,14591,14593,14621,14627, 260 | 14629,14633,14639,14653,14657,14669,14683,14699, 261 | 14713,14717,14723,14731,14737,14741,14747,14753, 262 | 14759,14767,14771,14779,14783,14797,14813,14821, 263 | 14827,14831,14843,14851,14867,14869,14879,14887, 264 | 14891,14897,14923,14929,14939,14947,14951,14957, 265 | 14969,14983,15013,15017,15031,15053,15061,15073, 266 | 15077,15083,15091,15101,15107,15121,15131,15137, 267 | 15139,15149,15161,15173,15187,15193,15199,15217, 268 | 15227,15233,15241,15259,15263,15269,15271,15277, 269 | 15287,15289,15299,15307,15313,15319,15329,15331, 270 | 15349,15359,15361,15373,15377,15383,15391,15401, 271 | 15413,15427,15439,15443,15451,15461,15467,15473, 272 | 15493,15497,15511,15527,15541,15551,15559,15569, 273 | 15581,15583,15601,15607,15619,15629,15641,15643, 274 | 15647,15649,15661,15667,15671,15679,15683,15727, 275 | 15731,15733,15737,15739,15749,15761,15767,15773, 276 | 15787,15791,15797,15803,15809,15817,15823,15859, 277 | 15877,15881,15887,15889,15901,15907,15913,15919, 278 | 15923,15937,15959,15971,15973,15991,16001,16007, 279 | 16033,16057,16061,16063,16067,16069,16073,16087, 280 | 16091,16097,16103,16111,16127,16139,16141,16183, 281 | 16187,16189,16193,16217,16223,16229,16231,16249, 282 | 16253,16267,16273,16301,16319,16333,16339,16349, 283 | 16361,16363,16369,16381,16411,16417,16421,16427, 284 | 16433,16447,16451,16453,16477,16481,16487,16493, 285 | 16519,16529,16547,16553,16561,16567,16573,16603, 286 | 16607,16619,16631,16633,16649,16651,16657,16661, 287 | 16673,16691,16693,16699,16703,16729,16741,16747, 288 | 16759,16763,16787,16811,16823,16829,16831,16843, 289 | 16871,16879,16883,16889,16901,16903,16921,16927, 290 | 16931,16937,16943,16963,16979,16981,16987,16993, 291 | 17011,17021,17027,17029,17033,17041,17047,17053, 292 | 17077,17093,17099,17107,17117,17123,17137,17159, 293 | 17167,17183,17189,17191,17203,17207,17209,17231, 294 | 17239,17257,17291,17293,17299,17317,17321,17327, 295 | 17333,17341,17351,17359,17377,17383,17387,17389, 296 | 17393,17401,17417,17419,17431,17443,17449,17467, 297 | 17471,17477,17483,17489,17491,17497,17509,17519, 298 | 17539,17551,17569,17573,17579,17581,17597,17599, 299 | 17609,17623,17627,17657,17659,17669,17681,17683, 300 | 17707,17713,17729,17737,17747,17749,17761,17783, 301 | 17789,17791,17807,17827,17837,17839,17851,17863, 302 | #endif 303 | }; 304 | 305 | static int dbnrand(int pseudorand, BIGNUM *rnd, int bits, int top, int bottom) 306 | { 307 | unsigned char *buf=NULL; 308 | int ret=0,bit,bytes,mask; 309 | /* PATCHED[needless for determinism] 310 | time_t tim; */ 311 | 312 | if (bits == 0) 313 | { 314 | BN_zero(rnd); 315 | return 1; 316 | } 317 | 318 | bytes=(bits+7)/8; 319 | bit=(bits-1)%8; 320 | mask=0xff<<(bit+1); 321 | 322 | buf=(unsigned char *)OPENSSL_malloc(bytes); 323 | if (buf == NULL) 324 | { 325 | BNerr(BN_F_BNRAND,ERR_R_MALLOC_FAILURE); 326 | goto err; 327 | } 328 | 329 | /* make a random number and set the top and bottom bits */ 330 | /* PATCHED[we do not want more entropy] 331 | time(&tim); 332 | RAND_add(&tim,sizeof(tim),0.0); */ 333 | 334 | if (pseudorand) 335 | { 336 | assert(RAND_get_rand_method() == &dRAND_method); 337 | if (RAND_pseudo_bytes(buf, bytes) == -1) 338 | goto err; 339 | } 340 | else 341 | { 342 | assert(RAND_get_rand_method() == &dRAND_method); 343 | if (RAND_bytes(buf, bytes) <= 0) 344 | goto err; 345 | } 346 | 347 | #if 1 348 | if (pseudorand == 2) 349 | { 350 | /* generate patterns that are more likely to trigger BN 351 | library bugs */ 352 | int i; 353 | unsigned char c; 354 | 355 | for (i = 0; i < bytes; i++) 356 | { 357 | assert(RAND_get_rand_method() == &dRAND_method); 358 | RAND_pseudo_bytes(&c, 1); 359 | if (c >= 128 && i > 0) 360 | buf[i] = buf[i-1]; 361 | else if (c < 42) 362 | buf[i] = 0; 363 | else if (c < 84) 364 | buf[i] = 255; 365 | } 366 | } 367 | #endif 368 | 369 | if (top != -1) 370 | { 371 | if (top) 372 | { 373 | if (bit == 0) 374 | { 375 | buf[0]=1; 376 | buf[1]|=0x80; 377 | } 378 | else 379 | { 380 | buf[0]|=(3<<(bit-1)); 381 | } 382 | } 383 | else 384 | { 385 | buf[0]|=(1<neg || BN_is_zero(range)) 425 | { 426 | BNerr(BN_F_BN_RAND_RANGE, BN_R_INVALID_RANGE); 427 | return 0; 428 | } 429 | 430 | n = BN_num_bits(range); /* n > 0 */ 431 | 432 | /* BN_is_bit_set(range, n - 1) always holds */ 433 | 434 | if (n == 1) 435 | BN_zero(r); 436 | else if (!BN_is_bit_set(range, n - 2) && !BN_is_bit_set(range, n - 3)) 437 | { 438 | /* range = 100..._2, 439 | * so 3*range (= 11..._2) is exactly one bit longer than range */ 440 | do 441 | { 442 | if (!bn_rand(r, n + 1, -1, 0)) return 0; 443 | /* If r < 3*range, use r := r MOD range 444 | * (which is either r, r - range, or r - 2*range). 445 | * Otherwise, iterate once more. 446 | * Since 3*range = 11..._2, each iteration succeeds with 447 | * probability >= .75. */ 448 | if (BN_cmp(r ,range) >= 0) 449 | { 450 | if (!BN_sub(r, r, range)) return 0; 451 | if (BN_cmp(r, range) >= 0) 452 | if (!BN_sub(r, r, range)) return 0; 453 | } 454 | 455 | if (!--count) 456 | { 457 | BNerr(BN_F_BN_RAND_RANGE, BN_R_TOO_MANY_ITERATIONS); 458 | return 0; 459 | } 460 | 461 | } 462 | while (BN_cmp(r, range) >= 0); 463 | } 464 | else 465 | { 466 | do 467 | { 468 | /* range = 11..._2 or range = 101..._2 */ 469 | if (!bn_rand(r, n, -1, 0)) return 0; 470 | 471 | if (!--count) 472 | { 473 | BNerr(BN_F_BN_RAND_RANGE, BN_R_TOO_MANY_ITERATIONS); 474 | return 0; 475 | } 476 | } 477 | while (BN_cmp(r, range) >= 0); 478 | } 479 | 480 | bn_check_top(r); 481 | return 1; 482 | } 483 | 484 | int dBN_pseudo_rand_range(BIGNUM *r, const BIGNUM *range) 485 | { 486 | /* PATCHED[rely on the deterministic version] */ 487 | return dbn_rand_range(1, r, range); 488 | } 489 | 490 | static int witness(BIGNUM *w, const BIGNUM *a, const BIGNUM *a1, 491 | const BIGNUM *a1_odd, int k, BN_CTX *ctx, BN_MONT_CTX *mont) 492 | { 493 | if (!BN_mod_exp_mont(w, w, a1_odd, a, ctx, mont)) /* w := w^a1_odd mod a */ 494 | return -1; 495 | if (BN_is_one(w)) 496 | return 0; /* probably prime */ 497 | if (BN_cmp(w, a1) == 0) 498 | return 0; /* w == -1 (mod a), 'a' is probably prime */ 499 | while (--k) 500 | { 501 | if (!BN_mod_mul(w, w, w, a, ctx)) /* w := w^2 mod a */ 502 | return -1; 503 | if (BN_is_one(w)) 504 | return 1; /* 'a' is composite, otherwise a previous 'w' would 505 | * have been == -1 (mod 'a') */ 506 | if (BN_cmp(w, a1) == 0) 507 | return 0; /* w == -1 (mod a), 'a' is probably prime */ 508 | } 509 | /* If we get here, 'w' is the (a-1)/2-th power of the original 'w', 510 | * and it is neither -1 nor +1 -- so 'a' cannot be prime */ 511 | bn_check_top(w); 512 | return 1; 513 | } 514 | 515 | int dBN_is_prime_fasttest_ex(const BIGNUM *a, int checks, BN_CTX *ctx_passed, 516 | int do_trial_division, BN_GENCB *cb) 517 | { 518 | int i, j, ret = -1; 519 | int k; 520 | BN_CTX *ctx = NULL; 521 | BIGNUM *A1, *A1_odd, *check; /* taken from ctx */ 522 | BN_MONT_CTX *mont = NULL; 523 | const BIGNUM *A = NULL; 524 | 525 | if (BN_cmp(a, BN_value_one()) <= 0) 526 | return 0; 527 | 528 | if (checks == BN_prime_checks) 529 | checks = BN_prime_checks_for_size(BN_num_bits(a)); 530 | 531 | /* first look for small factors */ 532 | if (!BN_is_odd(a)) 533 | /* a is even => a is prime if and only if a == 2 */ 534 | return BN_is_word(a, 2); 535 | if (do_trial_division) 536 | { 537 | for (i = 1; i < NUMPRIMES; i++) 538 | if (BN_mod_word(a, primes[i]) == 0) 539 | return 0; 540 | if(!BN_GENCB_call(cb, 1, -1)) 541 | goto err; 542 | } 543 | 544 | if (ctx_passed != NULL) 545 | ctx = ctx_passed; 546 | else 547 | if ((ctx=BN_CTX_new()) == NULL) 548 | goto err; 549 | BN_CTX_start(ctx); 550 | 551 | /* A := abs(a) */ 552 | if (a->neg) 553 | { 554 | BIGNUM *t; 555 | if ((t = BN_CTX_get(ctx)) == NULL) goto err; 556 | BN_copy(t, a); 557 | t->neg = 0; 558 | A = t; 559 | } 560 | else 561 | A = a; 562 | 563 | A1 = BN_CTX_get(ctx); 564 | A1_odd = BN_CTX_get(ctx); 565 | check = BN_CTX_get(ctx); 566 | if (check == NULL) goto err; 567 | /* compute A1 := A - 1 */ 568 | if (!BN_copy(A1, A)) 569 | goto err; 570 | if (!BN_sub_word(A1, 1)) 571 | goto err; 572 | if (BN_is_zero(A1)) 573 | { 574 | ret = 0; 575 | goto err; 576 | } 577 | 578 | /* write A1 as A1_odd * 2^k */ 579 | k = 1; 580 | while (!BN_is_bit_set(A1, k)) 581 | k++; 582 | if (!BN_rshift(A1_odd, A1, k)) 583 | goto err; 584 | 585 | /* Montgomery setup for computations mod A */ 586 | mont = BN_MONT_CTX_new(); 587 | if (mont == NULL) 588 | goto err; 589 | if (!BN_MONT_CTX_set(mont, A, ctx)) 590 | goto err; 591 | 592 | for (i = 0; i < checks; i++) 593 | { 594 | /* PATCHED[use our dBN_pseudo_rand_range()] */ 595 | if (!dBN_pseudo_rand_range(check, A1)) 596 | goto err; 597 | if (!BN_add_word(check, 1)) 598 | goto err; 599 | /* now 1 <= check < A */ 600 | 601 | j = witness(check, A, A1, A1_odd, k, ctx, mont); 602 | if (j == -1) goto err; 603 | if (j) 604 | { 605 | ret=0; 606 | goto err; 607 | } 608 | if(!BN_GENCB_call(cb, 1, i)) 609 | goto err; 610 | } 611 | ret=1; 612 | err: 613 | if (ctx != NULL) 614 | { 615 | BN_CTX_end(ctx); 616 | if (ctx_passed == NULL) 617 | BN_CTX_free(ctx); 618 | } 619 | if (mont != NULL) 620 | BN_MONT_CTX_free(mont); 621 | 622 | return(ret); 623 | } 624 | 625 | static int dprobable_prime_dh(BIGNUM *rnd, int bits, 626 | const BIGNUM *add, const BIGNUM *rem, BN_CTX *ctx) 627 | { 628 | int i,ret=0; 629 | BIGNUM *t1; 630 | 631 | BN_CTX_start(ctx); 632 | if ((t1 = BN_CTX_get(ctx)) == NULL) goto err; 633 | 634 | /* PATCHED[use our random generator here] */ 635 | if (!dBN_rand(rnd,bits,0,1)) goto err; 636 | 637 | /* we need ((rnd-rem) % add) == 0 */ 638 | 639 | if (!BN_mod(t1,rnd,add,ctx)) goto err; 640 | if (!BN_sub(rnd,rnd,t1)) goto err; 641 | if (rem == NULL) 642 | { if (!BN_add_word(rnd,1)) goto err; } 643 | else 644 | { if (!BN_add(rnd,rnd,rem)) goto err; } 645 | 646 | /* we now have a random number 'rand' to test. */ 647 | 648 | loop: for (i=1; i maxdelta) goto again; 740 | goto loop; 741 | } 742 | } 743 | if (!BN_add_word(rnd,delta)) return(0); 744 | bn_check_top(rnd); 745 | return(1); 746 | } 747 | 748 | int dBN_generate_prime_ex(BIGNUM *ret, int bits, int safe, 749 | const BIGNUM *add, const BIGNUM *rem, BN_GENCB *cb) 750 | { 751 | BIGNUM *t; 752 | int found=0; 753 | int i,j,c1=0; 754 | BN_CTX *ctx; 755 | int checks = BN_prime_checks_for_size(bits); 756 | 757 | ctx=BN_CTX_new(); 758 | if (ctx == NULL) goto err; 759 | BN_CTX_start(ctx); 760 | t = BN_CTX_get(ctx); 761 | if(!t) goto err; 762 | loop: 763 | /* make a random number and set the top and bottom bits */ 764 | 765 | if (add == NULL) 766 | { 767 | /* PATCHED[use the deterministic version] */ 768 | if (!dprobable_prime(ret,bits)) goto err; 769 | } 770 | else 771 | { 772 | if (safe) 773 | { 774 | /* PATCHED[use the deterministic version] */ 775 | if (!dprobable_prime_dh_safe(ret,bits,add,rem,ctx)) 776 | goto err; 777 | } 778 | else 779 | { 780 | /* PATCHED[use the deterministic version] */ 781 | if (!dprobable_prime_dh(ret,bits,add,rem,ctx)) 782 | goto err; 783 | } 784 | } 785 | 786 | /* if (BN_mod_word(ret,(BN_ULONG)3) == 1) goto loop; */ 787 | if(!BN_GENCB_call(cb, 0, c1++)) 788 | /* aborted */ 789 | goto err; 790 | 791 | if (!safe) 792 | { 793 | /* PATCHED[use our dBN_is_prime_fasttest_ex()] */ 794 | i=dBN_is_prime_fasttest_ex(ret,checks,ctx,0,cb); 795 | if (i == -1) goto err; 796 | if (i == 0) goto loop; 797 | } 798 | else 799 | { 800 | /* for "safe prime" generation, 801 | * check that (p-1)/2 is prime. 802 | * Since a prime is odd, We just 803 | * need to divide by 2 */ 804 | if (!BN_rshift1(t,ret)) goto err; 805 | 806 | for (i=0; i 16 | 17 | /* These functions have been slightly modified so as to make sure 18 | no entropy is generated whenever called. */ 19 | 20 | int dBN_rand(BIGNUM *rnd, int bits, int top, int bottom); 21 | int dBN_pseudo_rand(BIGNUM *rnd, int bits, int top, int bottom); 22 | int dBN_pseudo_rand_range(BIGNUM *r, const BIGNUM *range); 23 | int dBN_is_prime_fasttest_ex(const BIGNUM *a, int checks, BN_CTX *ctx_passed, 24 | int do_trial_division, BN_GENCB *cb); 25 | int dBN_generate_prime_ex(BIGNUM *ret, int bits, int safe, 26 | const BIGNUM *add, const BIGNUM *rem, BN_GENCB *cb); 27 | 28 | /* Display the given big number on the standard output. */ 29 | int dBN_print(BIGNUM *n); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /src/dopenssl/bn.hh: -------------------------------------------------------------------------------- 1 | extern "C" 2 | { 3 | # include 4 | } 5 | -------------------------------------------------------------------------------- /src/dopenssl/rand.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013, infinit.io 3 | * 4 | * This software is provided "as is" without warranty of any kind, 5 | * either expressed or implied, including but not limited to the 6 | * implied warranties of fitness for a particular purpose. 7 | * 8 | * See the LICENSE file for more information on the terms and 9 | * conditions. 10 | */ 11 | 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include 20 | #include 21 | 22 | /* 23 | * ---------- Original Functionalities ---------------------------------------- 24 | * 25 | * Based on the following OpenSSL files: 26 | * 27 | * crypto/rand/md_rand.c 28 | */ 29 | 30 | #define MD_DIGEST_LENGTH SHA_DIGEST_LENGTH 31 | 32 | #define MD_Update(a,b,c) EVP_DigestUpdate(a,b,c) 33 | #define MD_Final(a,b) EVP_DigestFinal_ex(a,b,NULL) 34 | #define MD_Init(a) EVP_DigestInit_ex(a,EVP_sha1(), NULL) 35 | #define MD(a,b,c) EVP_Digest(a,b,c,NULL,EVP_sha1(), NULL) 36 | 37 | #define ENTROPY_NEEDED 32 /* require 256 bits = 32 bytes of randomness */ 38 | 39 | #define STATE_SIZE 1023 40 | 41 | static unsigned int crypto_lock_rand = 0; /* may be set only when a thread 42 | * holds CRYPTO_LOCK_RAND 43 | * (to prevent double locking) */ 44 | /* access to lockin_thread is synchronized by CRYPTO_LOCK_RAND2 */ 45 | static CRYPTO_THREADID locking_threadid; /* valid iff crypto_lock_rand is set */ 46 | 47 | static int state_num=0,state_index=0; 48 | static unsigned char state[STATE_SIZE+MD_DIGEST_LENGTH]; 49 | static unsigned char md[MD_DIGEST_LENGTH]; 50 | static int md_count[2]={0,0}; 51 | static double entropy=0; 52 | static int initialized=0; 53 | 54 | static void dRAND_cleanup(void) 55 | { 56 | OPENSSL_cleanse(state,sizeof(state)); 57 | state_num=0; 58 | state_index=0; 59 | OPENSSL_cleanse(md,MD_DIGEST_LENGTH); 60 | md_count[0]=0; 61 | md_count[1]=0; 62 | entropy=0; 63 | initialized=0; 64 | 65 | /* PATCHED[so as to be deterministic, also reset the state and md 66 | variables] */ 67 | memset(state, 0x0, sizeof (state)); 68 | memset(md, 0x0, sizeof (md)); 69 | 70 | /* PATCHED[this section has been taken from ssleay_rand_bytes() in 71 | order to have enough 'md' to perform the operations] */ 72 | { 73 | /* In the output function only half of 'md' remains secret, 74 | * so we better make sure that the required entropy gets 75 | * 'evenly distributed' through 'state', our randomness pool. 76 | * The input function (ssleay_rand_add) chains all of 'md', 77 | * which makes it more suitable for this purpose. 78 | */ 79 | 80 | int n = STATE_SIZE; /* so that the complete pool gets accessed */ 81 | while (n > 0) 82 | { 83 | #if MD_DIGEST_LENGTH > 20 84 | # error "Please adjust DUMMY_SEED." 85 | #endif 86 | #define DUMMY_SEED "...................." /* at least MD_DIGEST_LENGTH */ 87 | /* Note that the seed does not matter, it's just that 88 | * ssleay_rand_add expects to have something to hash. */ 89 | /* PATCHED[the following line is a fix replacing ssleay_rand_add()] */ 90 | assert(RAND_get_rand_method() == &dRAND_method); 91 | RAND_add(DUMMY_SEED, MD_DIGEST_LENGTH, 0.0); 92 | n -= MD_DIGEST_LENGTH; 93 | } 94 | } 95 | } 96 | 97 | static void dRAND_add(const void *buf, int num, double add) 98 | { 99 | int i,j,k,st_idx; 100 | int md_c[2]; 101 | unsigned char local_md[MD_DIGEST_LENGTH]; 102 | EVP_MD_CTX m; 103 | int do_not_lock; 104 | 105 | /* 106 | * (Based on the rand(3) manpage) 107 | * 108 | * The input is chopped up into units of 20 bytes (or less for 109 | * the last block). Each of these blocks is run through the hash 110 | * function as follows: The data passed to the hash function 111 | * is the current 'md', the same number of bytes from the 'state' 112 | * (the location determined by in incremented looping index) as 113 | * the current 'block', the new key data 'block', and 'count' 114 | * (which is incremented after each use). 115 | * The result of this is kept in 'md' and also xored into the 116 | * 'state' at the same locations that were used as input into the 117 | * hash function. 118 | */ 119 | 120 | /* check if we already have the lock */ 121 | if (crypto_lock_rand) 122 | { 123 | CRYPTO_THREADID cur; 124 | CRYPTO_THREADID_current(&cur); 125 | CRYPTO_r_lock(CRYPTO_LOCK_RAND2); 126 | do_not_lock = !CRYPTO_THREADID_cmp(&locking_threadid, &cur); 127 | CRYPTO_r_unlock(CRYPTO_LOCK_RAND2); 128 | } 129 | else 130 | do_not_lock = 0; 131 | 132 | if (!do_not_lock) CRYPTO_w_lock(CRYPTO_LOCK_RAND); 133 | st_idx=state_index; 134 | 135 | /* use our own copies of the counters so that even 136 | * if a concurrent thread seeds with exactly the 137 | * same data and uses the same subarray there's _some_ 138 | * difference */ 139 | md_c[0] = md_count[0]; 140 | md_c[1] = md_count[1]; 141 | 142 | memcpy(local_md, md, sizeof md); 143 | 144 | /* state_index <= state_num <= STATE_SIZE */ 145 | state_index += num; 146 | if (state_index >= STATE_SIZE) 147 | { 148 | state_index%=STATE_SIZE; 149 | state_num=STATE_SIZE; 150 | } 151 | else if (state_num < STATE_SIZE) 152 | { 153 | if (state_index > state_num) 154 | state_num=state_index; 155 | } 156 | /* state_index <= state_num <= STATE_SIZE */ 157 | 158 | /* state[st_idx], ..., state[(st_idx + num - 1) % STATE_SIZE] 159 | * are what we will use now, but other threads may use them 160 | * as well */ 161 | 162 | md_count[1] += (num / MD_DIGEST_LENGTH) + (num % MD_DIGEST_LENGTH > 0); 163 | 164 | if (!do_not_lock) CRYPTO_w_unlock(CRYPTO_LOCK_RAND); 165 | 166 | EVP_MD_CTX_init(&m); 167 | for (i=0; i MD_DIGEST_LENGTH)?MD_DIGEST_LENGTH:j; 171 | 172 | MD_Init(&m); 173 | 174 | MD_Update(&m,local_md,MD_DIGEST_LENGTH); 175 | 176 | k=(st_idx+j)-STATE_SIZE; 177 | if (k > 0) 178 | { 179 | MD_Update(&m,&(state[st_idx]),j-k); 180 | MD_Update(&m,&(state[0]),k); 181 | } 182 | else 183 | MD_Update(&m,&(state[st_idx]),j); 184 | 185 | /* DO NOT REMOVE THE FOLLOWING CALL TO MD_Update()! */ 186 | MD_Update(&m,buf,j); 187 | /* We know that line may cause programs such as 188 | purify and valgrind to complain about use of 189 | uninitialized data. The problem is not, it's 190 | with the caller. Removing that line will make 191 | sure you get really bad randomness and thereby 192 | other problems such as very insecure keys. */ 193 | 194 | MD_Update(&m,(unsigned char *)&(md_c[0]),sizeof(md_c)); 195 | MD_Final(&m,local_md); 196 | md_c[1]++; 197 | 198 | buf=(const char *)buf + j; 199 | 200 | for (k=0; k= STATE_SIZE) 212 | st_idx=0; 213 | } 214 | } 215 | EVP_MD_CTX_cleanup(&m); 216 | 217 | if (!do_not_lock) CRYPTO_w_lock(CRYPTO_LOCK_RAND); 218 | /* Don't just copy back local_md into md -- this could mean that 219 | * other thread's seeding remains without effect (except for 220 | * the incremented counter). By XORing it we keep at least as 221 | * much entropy as fits into md. */ 222 | for (k = 0; k < (int)sizeof(md); k++) 223 | { 224 | md[k] ^= local_md[k]; 225 | } 226 | if (entropy < ENTROPY_NEEDED) /* stop counting when we have enough */ 227 | entropy += add; 228 | if (!do_not_lock) CRYPTO_w_unlock(CRYPTO_LOCK_RAND); 229 | 230 | #if !defined(OPENSSL_THREADS) && !defined(OPENSSL_SYS_WIN32) 231 | assert(md_c[1] == md_count[1]); 232 | #endif 233 | } 234 | 235 | static void dRAND_seed(const void *buf, int num) 236 | { 237 | /* PATCHED[this line is a fix of ssleay_rand_add()] */ 238 | assert(RAND_get_rand_method() == &dRAND_method); 239 | RAND_add(buf, num, (double)num); 240 | } 241 | 242 | static int dRAND_bytes(unsigned char *buf, int num) 243 | { 244 | int i,j,k,st_num,st_idx; 245 | int num_ceil; 246 | int ok; 247 | int md_c[2]; 248 | unsigned char local_md[MD_DIGEST_LENGTH]; 249 | EVP_MD_CTX m; 250 | 251 | if (num <= 0) 252 | return 1; 253 | 254 | EVP_MD_CTX_init(&m); 255 | /* round upwards to multiple of MD_DIGEST_LENGTH/2 */ 256 | num_ceil = (1 + (num-1)/(MD_DIGEST_LENGTH/2)) * (MD_DIGEST_LENGTH/2); 257 | 258 | /* 259 | * (Based on the rand(3) manpage:) 260 | * 261 | * For each group of 10 bytes (or less), we do the following: 262 | * 263 | * Input into the hash function the local 'md' (which is initialized from 264 | * the global 'md' before any bytes are generated), the bytes that are to 265 | * be overwritten by the random bytes, and bytes from the 'state' 266 | * (incrementing looping index). From this digest output (which is kept 267 | * in 'md'), the top (up to) 10 bytes are returned to the caller and the 268 | * bottom 10 bytes are xored into the 'state'. 269 | * 270 | * Finally, after we have finished 'num' random bytes for the 271 | * caller, 'count' (which is incremented) and the local and global 'md' 272 | * are fed into the hash function and the results are kept in the 273 | * global 'md'. 274 | */ 275 | 276 | CRYPTO_w_lock(CRYPTO_LOCK_RAND); 277 | 278 | /* prevent ssleay_rand_bytes() from trying to obtain the lock again */ 279 | CRYPTO_w_lock(CRYPTO_LOCK_RAND2); 280 | CRYPTO_THREADID_current(&locking_threadid); 281 | CRYPTO_w_unlock(CRYPTO_LOCK_RAND2); 282 | crypto_lock_rand = 1; 283 | 284 | if (!initialized) 285 | { 286 | /* PATCHED[the call to RAND_poll() has been removed here because 287 | injecting unwanted entropy] */ 288 | initialized = 1; 289 | } 290 | 291 | ok = (entropy >= ENTROPY_NEEDED); 292 | if (!ok) 293 | { 294 | /* If the PRNG state is not yet unpredictable, then seeing 295 | * the PRNG output may help attackers to determine the new 296 | * state; thus we have to decrease the entropy estimate. 297 | * Once we've had enough initial seeding we don't bother to 298 | * adjust the entropy count, though, because we're not ambitious 299 | * to provide *information-theoretic* randomness. 300 | * 301 | * NOTE: This approach fails if the program forks before 302 | * we have enough entropy. Entropy should be collected 303 | * in a separate input pool and be transferred to the 304 | * output pool only when the entropy limit has been reached. 305 | */ 306 | entropy -= num; 307 | if (entropy < 0) 308 | entropy = 0; 309 | } 310 | 311 | /* PATCHED[here the section filling the 'md' has been moved to 312 | RAND_cleanup()] */ 313 | 314 | st_idx=state_index; 315 | st_num=state_num; 316 | md_c[0] = md_count[0]; 317 | md_c[1] = md_count[1]; 318 | memcpy(local_md, md, sizeof md); 319 | 320 | state_index+=num_ceil; 321 | if (state_index > state_num) 322 | state_index %= state_num; 323 | 324 | /* state[st_idx], ..., state[(st_idx + num_ceil - 1) % st_num] 325 | * are now ours (but other threads may use them too) */ 326 | 327 | md_count[0] += 1; 328 | 329 | /* before unlocking, we must clear 'crypto_lock_rand' */ 330 | crypto_lock_rand = 0; 331 | CRYPTO_w_unlock(CRYPTO_LOCK_RAND); 332 | 333 | while (num > 0) 334 | { 335 | /* num_ceil -= MD_DIGEST_LENGTH/2 */ 336 | j=(num >= MD_DIGEST_LENGTH/2)?MD_DIGEST_LENGTH/2:num; 337 | num-=j; 338 | MD_Init(&m); 339 | MD_Update(&m,local_md,MD_DIGEST_LENGTH); 340 | MD_Update(&m,(unsigned char *)&(md_c[0]),sizeof(md_c)); 341 | 342 | /* The following line uses the supplied buffer as a small 343 | * source of entropy: since this buffer is often uninitialised 344 | * it may cause programs such as purify or valgrind to 345 | * complain. So for those builds it is not used: the removal 346 | * of such a small source of entropy has negligible impact on 347 | * security. 348 | */ 349 | /* PATCHED[the following line adds undeterminism and has therefore 350 | been removed] 351 | MD_Update(&m,buf,j); */ 352 | 353 | k=(st_idx+MD_DIGEST_LENGTH/2)-st_num; 354 | if (k > 0) 355 | { 356 | MD_Update(&m,&(state[st_idx]),MD_DIGEST_LENGTH/2-k); 357 | MD_Update(&m,&(state[0]),k); 358 | } 359 | else 360 | MD_Update(&m,&(state[st_idx]),MD_DIGEST_LENGTH/2); 361 | MD_Final(&m,local_md); 362 | 363 | for (i=0; i= st_num) 367 | st_idx=0; 368 | if (i < j) 369 | *(buf++)=local_md[i+MD_DIGEST_LENGTH/2]; 370 | } 371 | } 372 | 373 | MD_Init(&m); 374 | MD_Update(&m,(unsigned char *)&(md_c[0]),sizeof(md_c)); 375 | MD_Update(&m,local_md,MD_DIGEST_LENGTH); 376 | CRYPTO_w_lock(CRYPTO_LOCK_RAND); 377 | MD_Update(&m,md,MD_DIGEST_LENGTH); 378 | MD_Final(&m,md); 379 | CRYPTO_w_unlock(CRYPTO_LOCK_RAND); 380 | 381 | EVP_MD_CTX_cleanup(&m); 382 | if (ok) 383 | return(1); 384 | else 385 | { 386 | RANDerr(RAND_F_SSLEAY_RAND_BYTES,RAND_R_PRNG_NOT_SEEDED); 387 | ERR_add_error_data(1, "You need to read the OpenSSL FAQ, " 388 | "http://www.openssl.org/support/faq.html"); 389 | return(0); 390 | } 391 | } 392 | 393 | static int dRAND_pseudorand(unsigned char *buf, int num) 394 | { 395 | int ret; 396 | unsigned long err; 397 | 398 | assert(RAND_get_rand_method() == &dRAND_method); 399 | ret = RAND_bytes(buf, num); 400 | if (ret == 0) 401 | { 402 | err = ERR_peek_error(); 403 | if (ERR_GET_LIB(err) == ERR_LIB_RAND && 404 | ERR_GET_REASON(err) == RAND_R_PRNG_NOT_SEEDED) 405 | ERR_clear_error(); 406 | } 407 | 408 | return (ret); 409 | } 410 | 411 | static int dRAND_status(void) 412 | { 413 | CRYPTO_THREADID cur; 414 | int ret; 415 | int do_not_lock; 416 | 417 | CRYPTO_THREADID_current(&cur); 418 | /* check if we already have the lock 419 | * (could happen if a RAND_poll() implementation calls RAND_status()) */ 420 | if (crypto_lock_rand) 421 | { 422 | CRYPTO_r_lock(CRYPTO_LOCK_RAND2); 423 | do_not_lock = !CRYPTO_THREADID_cmp(&locking_threadid, &cur); 424 | CRYPTO_r_unlock(CRYPTO_LOCK_RAND2); 425 | } 426 | else 427 | do_not_lock = 0; 428 | 429 | if (!do_not_lock) 430 | { 431 | CRYPTO_w_lock(CRYPTO_LOCK_RAND); 432 | 433 | /* prevent ssleay_rand_bytes() from trying to obtain the lock again */ 434 | CRYPTO_w_lock(CRYPTO_LOCK_RAND2); 435 | CRYPTO_THREADID_cpy(&locking_threadid, &cur); 436 | CRYPTO_w_unlock(CRYPTO_LOCK_RAND2); 437 | crypto_lock_rand = 1; 438 | } 439 | 440 | if (!initialized) 441 | { 442 | /* PATCHED[the call to RAND_poll() has been removed here because 443 | injecting additional entropy] */ 444 | initialized = 1; 445 | } 446 | 447 | ret = entropy >= ENTROPY_NEEDED; 448 | if (!do_not_lock) 449 | { 450 | /* before unlocking, we must clear 'crypto_lock_rand' */ 451 | crypto_lock_rand = 0; 452 | 453 | CRYPTO_w_unlock(CRYPTO_LOCK_RAND); 454 | } 455 | 456 | return ret; 457 | } 458 | 459 | RAND_METHOD const dRAND_method = 460 | { 461 | dRAND_seed, 462 | dRAND_bytes, 463 | dRAND_cleanup, 464 | dRAND_add, 465 | dRAND_pseudorand, 466 | dRAND_status 467 | }; 468 | 469 | /* 470 | * ---------- Additional Functionalities -------------------------------------- 471 | */ 472 | 473 | static ENGINE* _engine = NULL; 474 | 475 | int dRAND_init() 476 | { 477 | if (_engine != NULL) 478 | return 0; 479 | 480 | assert(ENGINE_by_id("dRAND") == NULL); 481 | 482 | ENGINE_load_openssl(); 483 | ENGINE_load_dynamic(); 484 | ENGINE_load_builtin_engines(); 485 | ENGINE_register_all_RAND(); 486 | 487 | if ((_engine = ENGINE_new()) == NULL) 488 | return 0; 489 | if (ENGINE_set_id(_engine, "dRAND") == 0) 490 | return 0; 491 | if (ENGINE_set_name(_engine, 492 | "deterministic random implementation") == 0) 493 | return 0; 494 | if (ENGINE_init(_engine) == 0) 495 | return 0; 496 | if (ENGINE_set_RAND(_engine, &dRAND_method) == 0) 497 | return 0; 498 | if (ENGINE_add(_engine) == 0) 499 | return 0; 500 | 501 | assert(ENGINE_by_id("dRAND") == _engine); 502 | assert(ENGINE_get_default_RAND() != _engine); 503 | assert(RAND_get_rand_method() != &dRAND_method); 504 | 505 | return 1; 506 | } 507 | 508 | int dRAND_clean() 509 | { 510 | if (_engine == NULL) 511 | return 0; 512 | 513 | assert(ENGINE_by_id("dRAND") == _engine); 514 | assert(ENGINE_get_default_RAND() != _engine); 515 | assert(RAND_get_rand_method() != &dRAND_method); 516 | 517 | ENGINE_remove(_engine); 518 | if (ENGINE_finish(_engine) == 0) 519 | return 0; 520 | if (ENGINE_free(_engine) == 0) 521 | return 0; 522 | ENGINE_cleanup(); 523 | 524 | _engine = NULL; 525 | 526 | assert(ENGINE_by_id("dRAND") == NULL); 527 | 528 | return 1; 529 | } 530 | 531 | int dRAND_start(void) 532 | { 533 | if (_engine == NULL) 534 | return 0; 535 | 536 | assert(ENGINE_by_id("dRAND") == _engine); 537 | assert(ENGINE_get_default_RAND() != _engine); 538 | assert(RAND_get_rand_method() != &dRAND_method); 539 | 540 | if (ENGINE_register_RAND(_engine) == 0) 541 | return 0; 542 | if (ENGINE_set_default_RAND(_engine) == 0) 543 | return 0; 544 | /* Force the RAND to reinitialize. */ 545 | if (RAND_set_rand_engine(NULL) == 0) 546 | return 0; 547 | 548 | assert(ENGINE_by_id("dRAND") == _engine); 549 | assert(ENGINE_get_default_RAND() == _engine); 550 | assert(RAND_get_rand_method() == &dRAND_method); 551 | 552 | return 1; 553 | } 554 | 555 | int dRAND_stop(void) 556 | { 557 | if (_engine == NULL) 558 | return 0; 559 | 560 | assert(ENGINE_by_id("dRAND") == _engine); 561 | assert(ENGINE_get_default_RAND() == _engine); 562 | assert(RAND_get_rand_method() == &dRAND_method); 563 | 564 | ENGINE_unregister_RAND(_engine); 565 | /* Force the RAND to reinitialize. */ 566 | if (RAND_set_rand_engine(NULL) == 0) 567 | return 0; 568 | 569 | assert(ENGINE_by_id("dRAND") == _engine); 570 | assert(ENGINE_get_default_RAND() != _engine); 571 | assert(RAND_get_rand_method() != &dRAND_method); 572 | 573 | return 1; 574 | } 575 | 576 | int dRAND_reset(void) 577 | { 578 | if (_engine == NULL) 579 | return 0; 580 | 581 | assert(ENGINE_by_id("dRAND") == _engine); 582 | assert(ENGINE_get_default_RAND() == _engine); 583 | assert(RAND_get_rand_method() == &dRAND_method); 584 | 585 | RAND_cleanup(); 586 | 587 | assert(ENGINE_by_id("dRAND") == _engine); 588 | assert(ENGINE_get_default_RAND() == _engine); 589 | assert(RAND_get_rand_method() == &dRAND_method); 590 | 591 | return 1; 592 | } 593 | 594 | void dRAND_state(void) 595 | { 596 | unsigned int i; 597 | 598 | printf("dRAND state:\n"); 599 | printf(" state_num = %d\n", state_num); 600 | printf(" state_index = %d\n", state_index); 601 | printf(" state = "); 602 | for (i = 0; i < sizeof (state); ++i) 603 | printf("%02x", state[i]); 604 | printf("\n"); 605 | printf(" md = "); 606 | for (i = 0; i < sizeof (md); ++i) 607 | printf("%02x", md[i]); 608 | printf("\n"); 609 | printf(" md_count = (%d %d)\n", md_count[0], md_count[1]); 610 | printf(" entropy = %f\n", entropy); 611 | printf(" initialized = %d\n", initialized); 612 | } 613 | 614 | char *dRAND_fingerprint(void) 615 | { 616 | char *data = (char*)malloc(MD_DIGEST_LENGTH + 1); 617 | memset(data, 0x0, MD_DIGEST_LENGTH + 1); 618 | 619 | EVP_MD_CTX ctx; 620 | 621 | EVP_MD_CTX_init(&ctx); 622 | 623 | MD_Init(&ctx); 624 | 625 | MD_Update(&ctx, &state_num, sizeof (state_num)); 626 | MD_Update(&ctx, &state_index, sizeof (state_index)); 627 | MD_Update(&ctx, &state, sizeof (state)); 628 | MD_Update(&ctx, &md, sizeof (md)); 629 | MD_Update(&ctx, &md_count, sizeof (md_count)); 630 | MD_Update(&ctx, &entropy, sizeof (entropy)); 631 | MD_Update(&ctx, &initialized, sizeof (initialized)); 632 | 633 | MD_Final(&ctx, (unsigned char*)data); 634 | 635 | EVP_MD_CTX_cleanup(&ctx); 636 | 637 | static char const* alphabet = "0123456789abcdef"; 638 | unsigned int i; 639 | 640 | char *fingerprint = (char*)malloc(MD_DIGEST_LENGTH * 2 + 1); 641 | memset(fingerprint, 0x0, MD_DIGEST_LENGTH * 2 + 1); 642 | 643 | for (i = 0; i < MD_DIGEST_LENGTH; ++i) 644 | { 645 | fingerprint[i * 2] = alphabet[(data[i] >> 4) & 0xf]; 646 | fingerprint[(i * 2) + 1] = alphabet[data[i] & 0xf]; 647 | } 648 | 649 | free(data); 650 | 651 | return (fingerprint); 652 | } 653 | -------------------------------------------------------------------------------- /src/dopenssl/rand.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013, infinit.io 3 | * 4 | * This software is provided "as is" without warranty of any kind, 5 | * either expressed or implied, including but not limited to the 6 | * implied warranties of fitness for a particular purpose. 7 | * 8 | * See the LICENSE file for more information on the terms and 9 | * conditions. 10 | */ 11 | 12 | #ifndef DOPENSSL_RAND_H 13 | # define DOPENSSL_RAND_H 14 | 15 | # include 16 | 17 | /* This structure defines the functions representing the deterministic 18 | implementation of a PNRG. 19 | In practice, these functions make sure not to directly 20 | add entropy neither to call functions which may do. */ 21 | extern RAND_METHOD const dRAND_method; 22 | 23 | /* Initialize the deterministic PNRG by setting up a new cryptographic 24 | ENGINE. */ 25 | int dRAND_init(); 26 | /* Clean the dRAND implementation from the list of engines. */ 27 | int dRAND_clean(); 28 | /* Register the dRAND implementation as the default one, ensuring that all 29 | RAND_* operations will be forwarded to the dRAND engine. */ 30 | int dRAND_start(void); 31 | /* Unregister the dRAND engine as the default implementation. */ 32 | int dRAND_stop(void); 33 | /* Reset the random implementation so as to make sure that PNRG is in its 34 | initial state. 35 | This function is particularly useful before seeding the PNRG assuming the 36 | caller expects the PNRG's state to be deterministic. */ 37 | int dRAND_reset(void); 38 | /* Display on the standard output the state of the PNRG. */ 39 | void dRAND_state(void); 40 | /* Return a string-based hexadecimal representation of the PNRG's state. 41 | Note that it is the responsibility of the caller to release the resources 42 | associated wit the returned string, via free(). */ 43 | char *dRAND_fingerprint(void); 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /src/dopenssl/rand.hh: -------------------------------------------------------------------------------- 1 | extern "C" 2 | { 3 | # include 4 | } 5 | -------------------------------------------------------------------------------- /src/dopenssl/rsa.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013, infinit.io 3 | * 4 | * This software is provided "as is" without warranty of any kind, 5 | * either expressed or implied, including but not limited to the 6 | * implied warranties of fitness for a particular purpose. 7 | * 8 | * See the LICENSE file for more information on the terms and 9 | * conditions. 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | 24 | /* 25 | * ---------- Additional Functionalities -------------------------------------- 26 | * 27 | * Based on the following OpenSSL files: 28 | * 29 | * crypto/rsa/rsa_gen.c 30 | */ 31 | 32 | RSA *dRSA_deduce_publickey(BIGNUM *N, 33 | const unsigned char *seed, size_t seed_length) 34 | { 35 | int bits,bitse,ok= -1; 36 | 37 | /* PATCHED[allocate an RSA key] */ 38 | RSA *rsa = RSA_new(); 39 | 40 | bits=BN_num_bits(N); 41 | bitse=(bits/2)+1; 42 | 43 | /* We need the RSA components non-NULL */ 44 | if(!rsa->n && ((rsa->n=BN_new()) == NULL)) goto err; 45 | if(!rsa->e && ((rsa->e=BN_new()) == NULL)) goto err; 46 | 47 | /* Initialize the 'private' component as unknown. */ 48 | rsa->d = NULL; 49 | rsa->p = NULL; 50 | rsa->q = NULL; 51 | rsa->dmp1 = NULL; 52 | rsa->dmq1 = NULL; 53 | rsa->iqmp = NULL; 54 | 55 | /* PATCHED[switch to our random generator in order to ensure 56 | determinism. note that the dRAND module must have been 57 | initialized] */ 58 | dRAND_start(); 59 | { 60 | assert(RAND_get_rand_method() == &dRAND_method); 61 | 62 | dRAND_reset(); 63 | RAND_seed(seed, seed_length); 64 | 65 | /* generate e */ 66 | /* PATCHED[here we use our prime generator which uses our deterministic 67 | random generator] */ 68 | if(!dBN_generate_prime_ex(rsa->e, bitse, 0, NULL, NULL, NULL)) 69 | goto err; 70 | } 71 | dRAND_stop(); 72 | 73 | /* assign n */ 74 | BN_copy(rsa->n, N); 75 | 76 | ok=1; 77 | err: 78 | if (ok == -1) 79 | { 80 | /* PATCHED[release the RSA structure and reinitialize the 81 | pointer to NULL] */ 82 | if (rsa != NULL) RSA_free(rsa); 83 | rsa = NULL; 84 | 85 | RSAerr(RSA_F_RSA_BUILTIN_KEYGEN,ERR_LIB_BN); 86 | } 87 | 88 | return rsa; 89 | } 90 | 91 | RSA *dRSA_deduce_privatekey(int bits, 92 | const unsigned char *seed, size_t seed_length) 93 | { 94 | BIGNUM *r0=NULL,*r1=NULL,*r2=NULL,*r3=NULL,*tmp; 95 | BIGNUM local_r0,local_d,local_p; 96 | BIGNUM *pr0,*d,*p; 97 | int bitse,bitsp,bitsq,ok= -1; 98 | BN_CTX *ctx=NULL; 99 | 100 | /* PATCHED[allocate an RSA key] */ 101 | RSA *rsa = RSA_new(); 102 | 103 | ctx=BN_CTX_new(); 104 | if (ctx == NULL) goto err; 105 | BN_CTX_start(ctx); 106 | r0 = BN_CTX_get(ctx); 107 | r1 = BN_CTX_get(ctx); 108 | r2 = BN_CTX_get(ctx); 109 | r3 = BN_CTX_get(ctx); 110 | if (r3 == NULL) goto err; 111 | 112 | bitse=(bits/2)+1; 113 | bitsp=(bits+1)/2; 114 | bitsq=bits-bitsp; 115 | 116 | /* We need the RSA components non-NULL */ 117 | if(!rsa->n && ((rsa->n=BN_new()) == NULL)) goto err; 118 | if(!rsa->d && ((rsa->d=BN_new()) == NULL)) goto err; 119 | if(!rsa->e && ((rsa->e=BN_new()) == NULL)) goto err; 120 | if(!rsa->p && ((rsa->p=BN_new()) == NULL)) goto err; 121 | if(!rsa->q && ((rsa->q=BN_new()) == NULL)) goto err; 122 | if(!rsa->dmp1 && ((rsa->dmp1=BN_new()) == NULL)) goto err; 123 | if(!rsa->dmq1 && ((rsa->dmq1=BN_new()) == NULL)) goto err; 124 | if(!rsa->iqmp && ((rsa->iqmp=BN_new()) == NULL)) goto err; 125 | 126 | /* PATCHED[switch to our random generator in order to ensure 127 | determinism. note that the dRAND module must have been 128 | initialized] */ 129 | dRAND_start(); 130 | { 131 | assert(RAND_get_rand_method() == &dRAND_method); 132 | 133 | dRAND_reset(); 134 | RAND_seed(seed, seed_length); 135 | 136 | /* generate e */ 137 | /* PATCHED[use our prime generator which uses our deterministic 138 | random generator] */ 139 | if(!dBN_generate_prime_ex(rsa->e, bitse, 0, NULL, NULL, NULL)) 140 | goto err; 141 | 142 | /* generate p and q */ 143 | for (;;) 144 | { 145 | if(!dBN_generate_prime_ex(rsa->p, bitsp, 0, NULL, NULL, NULL)) 146 | goto err; 147 | if (!BN_sub(r2,rsa->p,BN_value_one())) goto err; 148 | if (!BN_gcd(r1,r2,rsa->e,ctx)) goto err; 149 | if (BN_is_one(r1)) break; 150 | } 151 | for (;;) 152 | { 153 | /* When generating ridiculously small keys, we can get stuck 154 | * continually regenerating the same prime values. Check for 155 | * this and bail if it happens 3 times. */ 156 | unsigned int degenerate = 0; 157 | do 158 | { 159 | if(!dBN_generate_prime_ex(rsa->q, bitsq, 0, NULL, NULL, NULL)) 160 | goto err; 161 | } while((BN_cmp(rsa->p, rsa->q) == 0) && (++degenerate < 3)); 162 | if(degenerate == 3) 163 | { 164 | ok = 0; /* we set our own err */ 165 | RSAerr(RSA_F_RSA_BUILTIN_KEYGEN,RSA_R_KEY_SIZE_TOO_SMALL); 166 | goto err; 167 | } 168 | if (!BN_sub(r2,rsa->q,BN_value_one())) goto err; 169 | if (!BN_gcd(r1,r2,rsa->e,ctx)) goto err; 170 | if (BN_is_one(r1)) 171 | break; 172 | } 173 | } 174 | dRAND_stop(); 175 | 176 | if (BN_cmp(rsa->p,rsa->q) < 0) 177 | { 178 | tmp=rsa->p; 179 | rsa->p=rsa->q; 180 | rsa->q=tmp; 181 | } 182 | 183 | /* calculate n */ 184 | if (!BN_mul(rsa->n,rsa->p,rsa->q,ctx)) goto err; 185 | 186 | /* calculate d */ 187 | if (!BN_sub(r1,rsa->p,BN_value_one())) goto err; /* p-1 */ 188 | if (!BN_sub(r2,rsa->q,BN_value_one())) goto err; /* q-1 */ 189 | if (!BN_mul(r0,r1,r2,ctx)) goto err; /* (p-1)(q-1) */ 190 | if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) 191 | { 192 | pr0 = &local_r0; 193 | BN_with_flags(pr0, r0, BN_FLG_CONSTTIME); 194 | } 195 | else 196 | pr0 = r0; 197 | if (!BN_mod_inverse(rsa->d,rsa->e,pr0,ctx)) goto err; /* d */ 198 | 199 | /* set up d for correct BN_FLG_CONSTTIME flag */ 200 | if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) 201 | { 202 | d = &local_d; 203 | BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME); 204 | } 205 | else 206 | d = rsa->d; 207 | 208 | /* calculate d mod (p-1) */ 209 | if (!BN_mod(rsa->dmp1,d,r1,ctx)) goto err; 210 | 211 | /* calculate d mod (q-1) */ 212 | if (!BN_mod(rsa->dmq1,d,r2,ctx)) goto err; 213 | 214 | /* calculate inverse of q mod p */ 215 | if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) 216 | { 217 | p = &local_p; 218 | BN_with_flags(p, rsa->p, BN_FLG_CONSTTIME); 219 | } 220 | else 221 | p = rsa->p; 222 | if (!BN_mod_inverse(rsa->iqmp,rsa->q,p,ctx)) goto err; 223 | 224 | ok=1; 225 | err: 226 | if (ok == -1) 227 | { 228 | /* PATCHED[release the RSA structure and reinitialize the 229 | pointer to NULL] */ 230 | if (rsa != NULL) RSA_free(rsa); 231 | rsa = NULL; 232 | 233 | RSAerr(RSA_F_RSA_BUILTIN_KEYGEN,ERR_LIB_BN); 234 | } 235 | if (ctx != NULL) 236 | { 237 | BN_CTX_end(ctx); 238 | BN_CTX_free(ctx); 239 | } 240 | 241 | return rsa; 242 | } 243 | 244 | int dRSA_cmp_publickey(RSA *a, RSA *b) 245 | { 246 | int x; 247 | 248 | assert(a->n != NULL); 249 | assert(a->e != NULL); 250 | assert(b->n != NULL); 251 | assert(b->e != NULL); 252 | 253 | if ((x = BN_cmp(a->n, b->n)) != 0) 254 | return x; 255 | if ((x = BN_cmp(a->e, b->e)) != 0) 256 | return x; 257 | 258 | return 0; 259 | } 260 | 261 | int dRSA_cmp_privatekey(RSA *a, RSA *b) 262 | { 263 | int x; 264 | 265 | assert(a->n != NULL); 266 | assert(a->e != NULL); 267 | assert(a->d != NULL); 268 | assert(a->p != NULL); 269 | assert(a->q != NULL); 270 | assert(a->dmp1 != NULL); 271 | assert(a->dmq1 != NULL); 272 | assert(a->iqmp != NULL); 273 | assert(b->n != NULL); 274 | assert(b->e != NULL); 275 | assert(b->d != NULL); 276 | assert(b->p != NULL); 277 | assert(b->q != NULL); 278 | assert(b->dmp1 != NULL); 279 | assert(b->dmq1 != NULL); 280 | assert(b->iqmp != NULL); 281 | 282 | if ((x = BN_cmp(a->n, b->n)) != 0) 283 | return x; 284 | if ((x = BN_cmp(a->e, b->e)) != 0) 285 | return x; 286 | if ((x = BN_cmp(a->d, b->d)) != 0) 287 | return x; 288 | if ((x = BN_cmp(a->p, b->p)) != 0) 289 | return x; 290 | if ((x = BN_cmp(a->q, b->q)) != 0) 291 | return x; 292 | if ((x = BN_cmp(a->dmp1, b->dmp1)) != 0) 293 | return x; 294 | if ((x = BN_cmp(a->dmq1, b->dmq1)) != 0) 295 | return x; 296 | if ((x = BN_cmp(a->iqmp, b->iqmp)) != 0) 297 | return x; 298 | 299 | return 0; 300 | } 301 | 302 | int dRSA_print(RSA *rsa) 303 | { 304 | char *n = NULL; 305 | char *e = NULL; 306 | char *d = NULL; 307 | char *p = NULL; 308 | char *q = NULL; 309 | char *dmp1 = NULL; 310 | char *dmq1 = NULL; 311 | char *iqmp = NULL; 312 | 313 | assert(rsa->n != NULL); 314 | assert(rsa->e != NULL); 315 | 316 | if ((n = BN_bn2hex(rsa->n)) == NULL) 317 | return 0; 318 | if ((e = BN_bn2hex(rsa->e)) == NULL) 319 | return 0; 320 | if (rsa->d != NULL) 321 | if ((d = BN_bn2hex(rsa->d)) == NULL) 322 | return 0; 323 | if (rsa->p != NULL) 324 | if ((p = BN_bn2hex(rsa->p)) == NULL) 325 | return 0; 326 | if (rsa->q != NULL) 327 | if ((q = BN_bn2hex(rsa->q)) == NULL) 328 | return 0; 329 | if (rsa->dmp1 != NULL) 330 | if ((dmp1 = BN_bn2hex(rsa->dmp1)) == NULL) 331 | return 0; 332 | if (rsa->dmq1 != NULL) 333 | if ((dmq1 = BN_bn2hex(rsa->dmq1)) == NULL) 334 | return 0; 335 | if (rsa->iqmp != NULL) 336 | if ((iqmp = BN_bn2hex(rsa->iqmp)) == NULL) 337 | return 0; 338 | 339 | printf("n=%s e=%s d=%s p=%s q=%s dmp1=%s dmq1=%s iqmp=%s\n", 340 | n, e, d, p, q, dmp1, dmq1, iqmp); 341 | 342 | OPENSSL_free(iqmp); 343 | OPENSSL_free(dmq1); 344 | OPENSSL_free(dmp1); 345 | OPENSSL_free(q); 346 | OPENSSL_free(p); 347 | OPENSSL_free(d); 348 | OPENSSL_free(n); 349 | OPENSSL_free(e); 350 | 351 | return 1; 352 | } 353 | -------------------------------------------------------------------------------- /src/dopenssl/rsa.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013, infinit.io 3 | * 4 | * This software is provided "as is" without warranty of any kind, 5 | * either expressed or implied, including but not limited to the 6 | * implied warranties of fitness for a particular purpose. 7 | * 8 | * See the LICENSE file for more information on the terms and 9 | * conditions. 10 | */ 11 | 12 | #ifndef DOPENSSL_RSA_H 13 | # define DOPENSSL_RSA_H 14 | 15 | # include 16 | 17 | /* Fill the public key of the given _rsa_ with the modulus _N_ and deduce the 18 | exponent with a deterministic PNRG seeded with the content provided. */ 19 | RSA *dRSA_deduce_publickey(BIGNUM *N, 20 | const unsigned char *seed, size_t seed_length); 21 | /* Deduce the whole private key _rsa_ of the given size in _bits_ by relying on 22 | a deterministic PNRG seeded with the content provided. */ 23 | RSA *dRSA_deduce_privatekey(int bits, 24 | const unsigned char *seed, size_t seed_length); 25 | /* Compare the public part of the two given RSA keys. */ 26 | int dRSA_cmp_publickey(RSA *a, RSA *b); 27 | /* Compare the private part of the two given RSA keys. */ 28 | int dRSA_cmp_privatekey(RSA *a, RSA *b); 29 | /* Display on the standard output the various numbers composing an RSA key. */ 30 | int dRSA_print(RSA *rsa); 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /src/dopenssl/rsa.hh: -------------------------------------------------------------------------------- 1 | extern "C" 2 | { 3 | # include 4 | } 5 | -------------------------------------------------------------------------------- /src/sample.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | int main(int argc, char **argv) 9 | { 10 | if (argc != 2) 11 | { 12 | printf("usage: %s [passphrase]\n", argv[0]); 13 | return(1); 14 | } 15 | 16 | unsigned int const bits = 2048; 17 | 18 | char const* passphrase = argv[1]; 19 | unsigned int const length = strlen(passphrase); 20 | unsigned int const size = bits / 8; 21 | unsigned int const occurences = size / length + 1; 22 | 23 | unsigned char* seed = malloc(occurences * length + 1); 24 | memset(seed, 0x0, occurences * length + 1); 25 | 26 | /* Concatenate the passphrase so as to create a 256-byte buffer */ 27 | unsigned int i; 28 | for (i = 0; i < occurences; i++) 29 | strncpy(seed + (i * length), passphrase, length); 30 | 31 | /* Initialize the deterministic random generator */ 32 | if (dRAND_init() != 1) 33 | { 34 | printf("[error] unable to initialize the random generator\n"); 35 | return (1); 36 | } 37 | 38 | /* Generate the RSA key */ 39 | RSA* rsa = NULL; 40 | 41 | if ((rsa = dRSA_deduce_privatekey(bits, seed, size)) == NULL) 42 | { 43 | printf("[error] unable to generate the RSA key pair\n"); 44 | return (1); 45 | } 46 | 47 | /* Display the RSA components */ 48 | RSA_print_fp(stdout, rsa, 0); 49 | 50 | /* Clean the resources */ 51 | if (dRAND_clean() != 1) 52 | { 53 | printf("[error] unable to clean the random generator\n"); 54 | return (1); 55 | } 56 | 57 | return (0); 58 | } 59 | -------------------------------------------------------------------------------- /tests/dopenssl/bn.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013, infinit.io 3 | * 4 | * This software is provided "as is" without warranty of any kind, 5 | * either expressed or implied, including but not limited to the 6 | * implied warranties of fitness for a particular purpose. 7 | * 8 | * See the LICENSE file for more information on the terms and 9 | * conditions. 10 | */ 11 | 12 | #include "dopenssl.h" 13 | 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | 20 | #include 21 | #include 22 | 23 | /*---------------. 24 | | Generate Prime | 25 | `---------------*/ 26 | 27 | static 28 | void 29 | test_generate_prime() 30 | { 31 | DOPENSSL_CHECK(dRAND_init() == 1); 32 | 33 | // Undeterministically randomly generate numbers should should therefore 34 | // all be different, with high probability. 35 | { 36 | BIGNUM* n1 = BN_new(); 37 | DOPENSSL_CHECK(BN_generate_prime_ex(n1, 1024, 0, 38 | NULL, NULL, NULL) == 1); 39 | 40 | BIGNUM* n2 = BN_new(); 41 | DOPENSSL_CHECK(BN_generate_prime_ex(n2, 1024, 0, 42 | NULL, NULL, NULL) == 1); 43 | 44 | BIGNUM* n3 = BN_new(); 45 | DOPENSSL_CHECK(BN_generate_prime_ex(n3, 1024, 0, 46 | NULL, NULL, NULL) == 1); 47 | 48 | DOPENSSL_CHECK(BN_cmp(n1, n2) != 0); 49 | DOPENSSL_CHECK(BN_cmp(n1, n3) != 0); 50 | DOPENSSL_CHECK(BN_cmp(n2, n3) != 0); 51 | 52 | BN_clear_free(n3); 53 | BN_clear_free(n2); 54 | BN_clear_free(n1); 55 | } 56 | 57 | // Generate numbers in a deterministic (but probabilist) way, by resetting the 58 | // seed for every random generation. 59 | // 60 | // Since based on the same seed, all the generated numbers should be equal. 61 | { 62 | char const* seed = 63 | "God exists since mathematics is consistent, " 64 | "and the Devil exists since we cannot prove it."; 65 | 66 | DOPENSSL_CHECK(dRAND_start() == 1); 67 | { 68 | DOPENSSL_CHECK(RAND_get_rand_method() == &dRAND_method); 69 | 70 | dRAND_reset(); 71 | RAND_seed(seed, strlen(seed)); 72 | BIGNUM* n1 = BN_new(); 73 | char* fingerprint1 = dRAND_fingerprint(); 74 | DOPENSSL_CHECK(fingerprint1 != NULL); 75 | DOPENSSL_CHECK(RAND_status() == 1); 76 | DOPENSSL_CHECK(dBN_generate_prime_ex(n1, 1024, 0, 77 | NULL, NULL, NULL) == 1); 78 | BIGNUM* n2 = BN_new(); 79 | char* fingerprint2 = dRAND_fingerprint(); 80 | DOPENSSL_CHECK(fingerprint2 != NULL); 81 | DOPENSSL_CHECK(RAND_status() == 1); 82 | DOPENSSL_CHECK(dBN_generate_prime_ex(n2, 2048, 0, 83 | NULL, NULL, NULL) == 1); 84 | 85 | dRAND_reset(); 86 | RAND_seed(seed, strlen(seed)); 87 | BIGNUM* n3 = BN_new(); 88 | char* fingerprint3 = dRAND_fingerprint(); 89 | DOPENSSL_CHECK(fingerprint3 != NULL); 90 | DOPENSSL_CHECK(RAND_status() == 1); 91 | DOPENSSL_CHECK(dBN_generate_prime_ex(n3, 1024, 0, 92 | NULL, NULL, NULL) == 1); 93 | BIGNUM* n4 = BN_new(); 94 | char* fingerprint4 = dRAND_fingerprint(); 95 | DOPENSSL_CHECK(fingerprint2 != NULL); 96 | DOPENSSL_CHECK(RAND_status() == 1); 97 | DOPENSSL_CHECK(dBN_generate_prime_ex(n4, 2048, 0, 98 | NULL, NULL, NULL) == 1); 99 | 100 | DOPENSSL_CHECK(strcmp(fingerprint1, fingerprint2) != 0); 101 | DOPENSSL_CHECK(strcmp(fingerprint3, fingerprint4) != 0); 102 | DOPENSSL_CHECK(strcmp(fingerprint1, fingerprint3) == 0); 103 | DOPENSSL_CHECK(strcmp(fingerprint2, fingerprint4) == 0); 104 | 105 | DOPENSSL_CHECK(strcmp(fingerprint1, 106 | "7ca2690d012e7b083d2975418e071fbfd20e41aa") == 0); 107 | DOPENSSL_CHECK(strcmp(fingerprint2, 108 | "39c11e1f1ee7c242e26876e3bbb33c2790afd48d") == 0); 109 | 110 | DOPENSSL_CHECK(BN_cmp(n1, n2) != 0); 111 | DOPENSSL_CHECK(BN_cmp(n3, n4) != 0); 112 | DOPENSSL_CHECK(BN_cmp(n1, n3) == 0); 113 | DOPENSSL_CHECK(BN_cmp(n2, n4) == 0); 114 | 115 | char* _n1 = BN_bn2hex(n1); 116 | DOPENSSL_CHECK(_n1 != NULL); 117 | char* _n2 = BN_bn2hex(n2); 118 | DOPENSSL_CHECK(_n2 != NULL); 119 | 120 | DOPENSSL_CHECK(strcmp(_n1, "C74382DE0EBE52A0127E37037452562FA88BAB317D3F096F9FCADFB069A0775B5C28EF7543A4D3A5BAA427D49D63CAD7AEAB5580056ECCC53D0714ACD893C8EAF9B7A094CE0AE3EEE7B5159FB3254061EE09D754D23414659BC91072D884CF6882517B984998CB052C6CF9D8D67C5C974EF475B6BEA45735B381A402FF6137C7") == 0); 121 | DOPENSSL_CHECK(strcmp(_n2, "DFE1212C3F96ED6AFD51EFDA80882B5DE38FD28F7EF0A9FB7E18C108AB59AFA942CE0C222CF48F0315326478269B3807D0E2D72B09A506C46ABBB8B9FA9258430134E117D711AFE69A0C7FBB5E3DB21F01FBEFCDC36E91EF461DC14490246C63C66FF0FF4BE03009416B85B93DC2083CD267788EDACC59F7CE1DD9D39A3115F1E99C3B2F2774BFCE5A25C593EB04B541A0CBE9DBA3C2A464C89AE590251701C27216E265C0EE6327BE8FB1D3B0C0BD70E3A775F23E23E1091CE37777D5C351DB6EC60E75E020F752CEF08F355117CDB79E4B428F585BFE02358F10971A42789CCD310D71FC7E944B6A53E4133F093C135B3BD9F0C1B15D8D63BA250BE691B51D") == 0); 122 | 123 | OPENSSL_free(_n2); 124 | OPENSSL_free(_n1); 125 | 126 | free(fingerprint4); 127 | free(fingerprint3); 128 | free(fingerprint2); 129 | free(fingerprint1); 130 | 131 | BN_clear_free(n4); 132 | BN_clear_free(n3); 133 | BN_clear_free(n2); 134 | BN_clear_free(n1); 135 | } 136 | DOPENSSL_CHECK(dRAND_stop() == 1); 137 | } 138 | 139 | // Likewise, generate numbers in a deterministic but safe way. 140 | { 141 | char const* seed = 142 | "A mathematician, like a painter or poet, is a maker of patterns. " 143 | "If his patterns are more permanent than theirs, it is because they " 144 | "are made with ideas."; 145 | 146 | DOPENSSL_CHECK(dRAND_start() == 1); 147 | { 148 | DOPENSSL_CHECK(RAND_get_rand_method() == &dRAND_method); 149 | 150 | BIGNUM* n1 = BN_new(); 151 | dRAND_reset(); 152 | RAND_seed(seed, strlen(seed)); 153 | char* fingerprint1 = dRAND_fingerprint(); 154 | DOPENSSL_CHECK(fingerprint1 != NULL); 155 | DOPENSSL_CHECK(RAND_status() == 1); 156 | DOPENSSL_CHECK(dBN_generate_prime_ex(n1, 512, 1, 157 | NULL, NULL, NULL) == 1); 158 | 159 | BIGNUM* n2 = BN_new(); 160 | dRAND_reset(); 161 | RAND_seed(seed, strlen(seed)); 162 | char* fingerprint2 = dRAND_fingerprint(); 163 | DOPENSSL_CHECK(fingerprint2 != NULL); 164 | DOPENSSL_CHECK(RAND_status() == 1); 165 | DOPENSSL_CHECK(dBN_generate_prime_ex(n2, 2048, 1, 166 | NULL, NULL, NULL) == 1); 167 | 168 | BIGNUM* n3 = BN_new(); 169 | dRAND_reset(); 170 | RAND_seed(seed, strlen(seed)); 171 | char* fingerprint3 = dRAND_fingerprint(); 172 | DOPENSSL_CHECK(fingerprint3 != NULL); 173 | DOPENSSL_CHECK(RAND_status() == 1); 174 | DOPENSSL_CHECK(dBN_generate_prime_ex(n3, 512, 1, 175 | NULL, NULL, NULL) == 1); 176 | 177 | DOPENSSL_CHECK(strcmp(fingerprint1, fingerprint2) == 0); 178 | DOPENSSL_CHECK(strcmp(fingerprint1, fingerprint3) == 0); 179 | DOPENSSL_CHECK(strcmp(fingerprint2, fingerprint3) == 0); 180 | 181 | DOPENSSL_CHECK(strcmp(fingerprint1, 182 | "6481dee291c5da35b63dbbd100fd290c32bba44c") == 0); 183 | 184 | DOPENSSL_CHECK(BN_cmp(n1, n2) != 0); 185 | DOPENSSL_CHECK(BN_cmp(n1, n3) == 0); 186 | DOPENSSL_CHECK(BN_cmp(n2, n3) != 0); 187 | 188 | char* _n1 = BN_bn2hex(n1); 189 | DOPENSSL_CHECK(_n1 != NULL); 190 | char* _n2 = BN_bn2hex(n2); 191 | DOPENSSL_CHECK(_n2 != NULL); 192 | 193 | DOPENSSL_CHECK(strcmp(_n1, "C62C91629AE1A666FD67619C5654E18F318F1B699763585E70D6355F93FF8ED633AD0E61A10E7F441F4A48961043C35926AE95714D72C113C0E27D21F122E7CF") == 0); 194 | DOPENSSL_CHECK(strcmp(_n2, "E2B61676A93745EED896C6C84B43BFA1515CDCCA40B55957B8C5470B25B70F80BFD2772A8A3F78ADF72D4CDEE24ABE0244EF3D0C3EAF848004A5D05F0AAFE3E880C93EB97B53D73C76E3D52170E06D32C9B3C7C5ECAF9EEF3EE1044C65723B4F99193B6668C179A8E7547A543D82368B091B28DD8AFDDEA6EBCEB3FA308E11D500A3C7CBF16A7CDB031B81317026852B4A2E24B3B82B58CFAB27A61F5F4CD09327BEBDE12AE5A2A395DA46DCF84B3E488B1E09856A65BC37D615DC43D727900E1D753E22ECF4B174E9BFF00CA6256ACB1F8A5D4DD9FF415A0E67AC4E5A1C2FDC9BFB64E474956E45EDFAAD776A3FC731A5D4E9098E739EB378ECE56469D02253") == 0); 195 | 196 | free(fingerprint3); 197 | free(fingerprint2); 198 | free(fingerprint1); 199 | 200 | BN_clear_free(n3); 201 | BN_clear_free(n2); 202 | BN_clear_free(n1); 203 | } 204 | DOPENSSL_CHECK(dRAND_stop() == 1); 205 | } 206 | 207 | DOPENSSL_CHECK(dRAND_clean() == 1); 208 | } 209 | 210 | /*-----. 211 | | Main | 212 | `-----*/ 213 | 214 | int 215 | main(int argc, 216 | char** argv) 217 | { 218 | test_generate_prime(); 219 | 220 | return (0); 221 | } 222 | -------------------------------------------------------------------------------- /tests/dopenssl/dopenssl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013, infinit.io 3 | * 4 | * This software is provided "as is" without warranty of any kind, 5 | * either expressed or implied, including but not limited to the 6 | * implied warranties of fitness for a particular purpose. 7 | * 8 | * See the LICENSE file for more information on the terms and 9 | * conditions. 10 | */ 11 | 12 | #ifndef DOPENSSL_H 13 | # define DOPENSSL_H 14 | 15 | # include 16 | # define DOPENSSL_CHECK(_condition_) \ 17 | assert(_condition_); 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /tests/dopenssl/rand.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013, infinit.io 3 | * 4 | * This software is provided "as is" without warranty of any kind, 5 | * either expressed or implied, including but not limited to the 6 | * implied warranties of fitness for a particular purpose. 7 | * 8 | * See the LICENSE file for more information on the terms and 9 | * conditions. 10 | */ 11 | 12 | #include "dopenssl.h" 13 | 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | 20 | #include 21 | #include 22 | 23 | /*------. 24 | | Basic | 25 | `------*/ 26 | 27 | static 28 | void 29 | test_basic() 30 | { 31 | DOPENSSL_CHECK(dRAND_init() == 1); 32 | 33 | // Note that the result of the RAND_status is not checked because 34 | // the PNRG has not been seeded, hence does not have enough entropy. 35 | 36 | DOPENSSL_CHECK(dRAND_start() == 1); 37 | { 38 | DOPENSSL_CHECK(RAND_get_rand_method() == &dRAND_method); 39 | 40 | RAND_status(); 41 | RAND_status(); 42 | 43 | dRAND_reset(); 44 | 45 | RAND_status(); 46 | } 47 | DOPENSSL_CHECK(dRAND_stop() == 1); 48 | 49 | RAND_status(); 50 | 51 | DOPENSSL_CHECK(dRAND_clean() == 1); 52 | } 53 | 54 | /*-----. 55 | | Seed | 56 | `-----*/ 57 | 58 | static 59 | void 60 | test_seed() 61 | { 62 | char const* seed = 63 | "Sir, an equation has no meaning for me " 64 | "unless it expresses a thought of GOD."; 65 | 66 | DOPENSSL_CHECK(dRAND_init() == 1); 67 | 68 | DOPENSSL_CHECK(dRAND_start() == 1); 69 | { 70 | DOPENSSL_CHECK(RAND_get_rand_method() == &dRAND_method); 71 | 72 | // Reset the random implementation and seed the random generator. 73 | dRAND_reset(); 74 | RAND_seed(seed, strlen(seed)); 75 | DOPENSSL_CHECK(RAND_status() == 1); 76 | char* fingerprint1 = dRAND_fingerprint(); 77 | DOPENSSL_CHECK(fingerprint1 != NULL); 78 | 79 | // Re-reset the random implementation and finally re-seed it: 80 | // the result should be the same as the first seeding. 81 | dRAND_reset(); 82 | RAND_seed(seed, strlen(seed)); 83 | DOPENSSL_CHECK(RAND_status() == 1); 84 | char* fingerprint2 = dRAND_fingerprint(); 85 | DOPENSSL_CHECK(fingerprint2 != NULL); 86 | 87 | DOPENSSL_CHECK(strcmp(fingerprint1, fingerprint2) == 0); 88 | 89 | DOPENSSL_CHECK(strcmp(fingerprint1, 90 | "a15e5e1860c9297f7055edb960067254822123ab") == 0); 91 | 92 | free(fingerprint2); 93 | free(fingerprint1); 94 | } 95 | DOPENSSL_CHECK(dRAND_stop() == 1); 96 | 97 | DOPENSSL_CHECK(dRAND_clean() == 1); 98 | } 99 | 100 | /*-----. 101 | | Main | 102 | `-----*/ 103 | 104 | int 105 | main(int argc, 106 | char** argv) 107 | { 108 | test_basic(); 109 | test_seed(); 110 | 111 | return (0); 112 | } 113 | -------------------------------------------------------------------------------- /tests/dopenssl/rsa.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013, infinit.io 3 | * 4 | * This software is provided "as is" without warranty of any kind, 5 | * either expressed or implied, including but not limited to the 6 | * implied warranties of fitness for a particular purpose. 7 | * 8 | * See the LICENSE file for more information on the terms and 9 | * conditions. 10 | */ 11 | 12 | #include "dopenssl.h" 13 | 14 | #include 15 | #include 16 | 17 | #include 18 | 19 | #include 20 | #include 21 | 22 | /*-------------------. 23 | | RSA Key Generation | 24 | `-------------------*/ 25 | 26 | static 27 | EVP_PKEY* 28 | _test_generate(unsigned int const length) 29 | { 30 | EVP_PKEY_CTX* context = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL); 31 | DOPENSSL_CHECK(context != NULL); 32 | 33 | DOPENSSL_CHECK(EVP_PKEY_keygen_init(context) > 0); 34 | 35 | DOPENSSL_CHECK(EVP_PKEY_CTX_set_rsa_keygen_bits(context, length) > 0); 36 | 37 | EVP_PKEY* key = NULL; 38 | 39 | DOPENSSL_CHECK(EVP_PKEY_keygen(context, &key) > 0); 40 | 41 | EVP_PKEY_CTX_free(context); 42 | 43 | return (key); 44 | } 45 | 46 | /*---------------. 47 | | RSA Encryption | 48 | `---------------*/ 49 | 50 | static 51 | void 52 | _test_encrypt(EVP_PKEY* key, 53 | unsigned char const* clear, 54 | size_t const clear_size, 55 | unsigned char** code, 56 | size_t* code_size) 57 | { 58 | // Prepare the context. 59 | 60 | EVP_PKEY_CTX* context = EVP_PKEY_CTX_new(key, NULL); 61 | DOPENSSL_CHECK(context != NULL); 62 | 63 | DOPENSSL_CHECK(EVP_PKEY_sign_init(context) > 0); 64 | 65 | DOPENSSL_CHECK(EVP_PKEY_CTX_ctrl(context, 66 | EVP_PKEY_RSA, 67 | -1, 68 | EVP_PKEY_CTRL_RSA_PADDING, 69 | RSA_NO_PADDING, // WARNING: insecure by design 70 | NULL) > 0); 71 | 72 | // Encrypt with the private key. 73 | 74 | size_t size; 75 | 76 | DOPENSSL_CHECK(clear != NULL); 77 | DOPENSSL_CHECK(clear_size > 0); 78 | 79 | DOPENSSL_CHECK(EVP_PKEY_sign(context, 80 | NULL, 81 | &size, 82 | clear, 83 | clear_size) > 0); 84 | 85 | DOPENSSL_CHECK(code != NULL); 86 | *code = (unsigned char*)OPENSSL_malloc(size); 87 | 88 | DOPENSSL_CHECK(EVP_PKEY_sign(context, 89 | *code, 90 | &size, 91 | clear, 92 | clear_size) > 0); 93 | 94 | DOPENSSL_CHECK(code_size != NULL); 95 | *code_size = size; 96 | 97 | // Clean the resources. 98 | 99 | EVP_PKEY_CTX_free(context); 100 | } 101 | 102 | /*---------------. 103 | | RSA Decryption | 104 | `---------------*/ 105 | 106 | static 107 | void 108 | _test_decrypt(EVP_PKEY* key, 109 | unsigned char const* code, 110 | size_t const code_size, 111 | unsigned char** clear, 112 | size_t* clear_size) 113 | { 114 | // Prepare the context. 115 | 116 | EVP_PKEY_CTX *context = EVP_PKEY_CTX_new(key, NULL); 117 | DOPENSSL_CHECK(context != NULL); 118 | 119 | DOPENSSL_CHECK(EVP_PKEY_verify_recover_init(context) > 0); 120 | 121 | DOPENSSL_CHECK(EVP_PKEY_CTX_ctrl(context, 122 | EVP_PKEY_RSA, 123 | -1, 124 | EVP_PKEY_CTRL_RSA_PADDING, 125 | RSA_NO_PADDING, // WARNING: insecure by design 126 | NULL) > 0); 127 | 128 | // Decrypt with the public key. 129 | 130 | size_t size; 131 | 132 | DOPENSSL_CHECK(code != NULL); 133 | DOPENSSL_CHECK(code_size > 0); 134 | 135 | DOPENSSL_CHECK(EVP_PKEY_verify_recover(context, 136 | NULL, 137 | &size, 138 | code, 139 | code_size) > 0); 140 | 141 | DOPENSSL_CHECK(clear != NULL); 142 | *clear = (unsigned char*)OPENSSL_malloc(size); 143 | 144 | DOPENSSL_CHECK(EVP_PKEY_verify_recover(context, 145 | *clear, 146 | &size, 147 | code, 148 | code_size) > 0); 149 | 150 | DOPENSSL_CHECK(clear != NULL); 151 | *clear_size = size; 152 | 153 | // Clean the resources. 154 | 155 | EVP_PKEY_CTX_free(context); 156 | } 157 | 158 | /*-------. 159 | | Deduce | 160 | `-------*/ 161 | 162 | static 163 | void 164 | test_deduce() 165 | { 166 | char const* seed = 167 | "Sir, an equation has no meaning for me " 168 | "unless it expresses a thought of GOD."; 169 | 170 | DOPENSSL_CHECK(dRAND_init() == 1); 171 | 172 | // Original key. 173 | EVP_PKEY* key = _test_generate(1024); 174 | DOPENSSL_CHECK(key != NULL); 175 | 176 | RSA* original = key->pkey.rsa; 177 | RSA* deduced1 = NULL; 178 | RSA* deduced2 = NULL; 179 | RSA* deduced3 = NULL; 180 | RSA* deduced4 = NULL; 181 | 182 | // Private Deducing 1. 183 | { 184 | deduced1 = dRSA_deduce_privatekey(BN_num_bits(original->n), 185 | (unsigned char const*)seed, 186 | strlen(seed)); 187 | DOPENSSL_CHECK(deduced1 != NULL); 188 | } 189 | 190 | // PrivateKey Deducing 2. 191 | { 192 | deduced2 = dRSA_deduce_privatekey(BN_num_bits(original->n), 193 | (unsigned char const*)seed, 194 | strlen(seed)); 195 | DOPENSSL_CHECK(deduced2 != NULL); 196 | } 197 | 198 | // PublicKey Deducing 3. 199 | { 200 | deduced3 = dRSA_deduce_publickey(deduced1->n, 201 | (unsigned char const*)seed, 202 | strlen(seed)); 203 | DOPENSSL_CHECK(deduced3 != NULL); 204 | } 205 | 206 | // PublicKey Deducing 4. 207 | { 208 | deduced4 = dRSA_deduce_publickey(deduced1->n, 209 | (unsigned char const*)seed, 210 | strlen(seed)); 211 | DOPENSSL_CHECK(deduced4 != NULL); 212 | } 213 | 214 | DOPENSSL_CHECK(dRSA_cmp_privatekey(deduced1, deduced2) == 0); 215 | DOPENSSL_CHECK(dRSA_cmp_publickey(deduced1, deduced3) == 0); 216 | DOPENSSL_CHECK(dRSA_cmp_publickey(deduced1, deduced4) == 0); 217 | DOPENSSL_CHECK(dRSA_cmp_publickey(deduced2, deduced3) == 0); 218 | DOPENSSL_CHECK(dRSA_cmp_publickey(deduced2, deduced4) == 0); 219 | DOPENSSL_CHECK(dRSA_cmp_publickey(deduced3, deduced4) == 0); 220 | 221 | char* n = BN_bn2hex(deduced1->n); 222 | DOPENSSL_CHECK(n != NULL); 223 | char* e = BN_bn2hex(deduced1->e); 224 | DOPENSSL_CHECK(e != NULL); 225 | char* d = BN_bn2hex(deduced1->d); 226 | DOPENSSL_CHECK(d != NULL); 227 | char* p = BN_bn2hex(deduced1->p); 228 | DOPENSSL_CHECK(p != NULL); 229 | char* q = BN_bn2hex(deduced1->q); 230 | DOPENSSL_CHECK(q != NULL); 231 | char* dmp1 = BN_bn2hex(deduced1->dmp1); 232 | DOPENSSL_CHECK(dmp1 != NULL); 233 | char* dmq1 = BN_bn2hex(deduced1->dmq1); 234 | DOPENSSL_CHECK(dmq1 != NULL); 235 | char* iqmp = BN_bn2hex(deduced1->iqmp); 236 | DOPENSSL_CHECK(iqmp != NULL); 237 | 238 | DOPENSSL_CHECK(strcmp(n, "D37F7E18E74D26101AA4DB65618C00553D86A25D398D6F112432561EA6BA1DFCA4ECD18AF9958973A56E9EC07222E42F7E84B1625554140AD3E840FFC81BC4BF830D49820A238A2C07846067D796FBD457A6B491B165E022D278D538EA6A197CBE548F6E669E0E7F3F6AA0907D4C5C41BAA80C191297A02A2963C7CC4B877025") == 0); 239 | DOPENSSL_CHECK(strcmp(e, "0190CB035742DEE8D2053AE254258DDA5422013425BDB1F8F4BA2C12AFCE48E8869273B7153ECAFE1D1C1AA9D38B54CAC2F0E6045C4009008235CBF11471527293") == 0); 240 | DOPENSSL_CHECK(strcmp(d, "BC412C05E9A4781E55830A43918487AB9765B18276C09DB8B996B281DB19596F064E0BF42F4D5E6329A762283979E06E7790CB1B02BBDE7EE6CE1B595FBA8511AC7D71034C5C0E338F6B90C57AE7E151F129B8D9076B0AFE9D078FEA4B35E2C3B161B20CEED2C5C19B7BADB231F51516404235E8EA4DBF97BEEE9E432D523B9B") == 0); 241 | DOPENSSL_CHECK(strcmp(p, "F0213E24F84C720370B550AA3A509B24E4D2B9B86482F5FA019E86D1454C67168B9C04DC9DE94E927E4452F23ED54F583E89AB1FED1B92678951483DD0174071") == 0); 242 | DOPENSSL_CHECK(strcmp(q, "E179D3E6F4AD5BDA9ADCEFA482B9711F94C6DDE17B57EDBCFEDD17BA356A837DDD83BB5FB8131105FDDF40FE7470CD2E7CFE03DFCA3DC9FA26437472EF1504F5") == 0); 243 | DOPENSSL_CHECK(strcmp(dmp1, "E5776B1025625319B2E1D9AD36B1741CF110D32417253B995AA95BBA4FECB09E88084C0E680CB3829019D3208F78857293F3F6B81C26B6E2B08ADE315B89868B") == 0); 244 | DOPENSSL_CHECK(strcmp(dmq1, "6B5C5B711D31EF831FB0514BB479D927467B5526E61F4BEB929DBB04A5324830C0F0A220D6CFB32C1E6EA5EAE3E30ACA0B3E9313302598C8DC4B8F30B3A44297") == 0); 245 | DOPENSSL_CHECK(strcmp(iqmp, "43B816E00C7BFC443ECE271127DDE351E76A4D85C69F78C0DC79E5349FEB2EE56A9B2F3811A66D6F04A85B7DAB983C4C69C6525672FD637207463C5F7FB78392") == 0); 246 | 247 | OPENSSL_free(iqmp); 248 | OPENSSL_free(dmq1); 249 | OPENSSL_free(dmp1); 250 | OPENSSL_free(q); 251 | OPENSSL_free(p); 252 | OPENSSL_free(d); 253 | OPENSSL_free(e); 254 | OPENSSL_free(n); 255 | 256 | RSA_free(deduced4); 257 | RSA_free(deduced3); 258 | RSA_free(deduced2); 259 | RSA_free(deduced1); 260 | 261 | EVP_PKEY_free(key); 262 | 263 | DOPENSSL_CHECK(dRAND_clean() == 1); 264 | } 265 | 266 | /*----------------. 267 | | Rotate & Derive | 268 | `----------------*/ 269 | 270 | static 271 | void 272 | test_rotate_and_derive() 273 | { 274 | // Initializing. 275 | DOPENSSL_CHECK(dRAND_init() == 1); 276 | 277 | // Note that the seed below has been carefully selected for its length to 278 | // match the RSA key size. 279 | char const* seed = 280 | "Before creation God did just pure mathematics. Then He thought it would " 281 | "be a pleasant change to do some applied. ---- Littlewood"; 282 | 283 | EVP_PKEY* key = _test_generate(1024); 284 | 285 | BIGNUM* N = BN_dup(key->pkey.rsa->n); 286 | 287 | // Rotation 1. 288 | unsigned char* rotated1_seed = NULL; 289 | size_t rotated1_seed_size = 0; 290 | RSA* rotated1_rsa; 291 | 292 | _test_encrypt(key, 293 | (unsigned char const*)seed, strlen(seed), 294 | &rotated1_seed, &rotated1_seed_size); 295 | 296 | rotated1_rsa = dRSA_deduce_privatekey(BN_num_bits(N), 297 | (unsigned char const*)rotated1_seed, 298 | rotated1_seed_size); 299 | DOPENSSL_CHECK(rotated1_rsa != NULL); 300 | 301 | // Rotation 2. 302 | unsigned char* rotated2_seed = NULL; 303 | size_t rotated2_seed_size = 0; 304 | RSA* rotated2_rsa; 305 | 306 | _test_encrypt(key, 307 | rotated1_seed, rotated1_seed_size, 308 | &rotated2_seed, &rotated2_seed_size); 309 | 310 | rotated2_rsa = dRSA_deduce_privatekey(BN_num_bits(N), 311 | (unsigned char const*)rotated2_seed, 312 | rotated2_seed_size); 313 | DOPENSSL_CHECK(rotated2_rsa != NULL); 314 | 315 | // Rotation 3. 316 | unsigned char* rotated3_seed = NULL; 317 | size_t rotated3_seed_size = 0; 318 | RSA* rotated3_rsa; 319 | 320 | _test_encrypt(key, 321 | rotated2_seed, rotated2_seed_size, 322 | &rotated3_seed, &rotated3_seed_size); 323 | 324 | rotated3_rsa = dRSA_deduce_privatekey(BN_num_bits(N), 325 | (unsigned char const*)rotated3_seed, 326 | rotated3_seed_size); 327 | DOPENSSL_CHECK(rotated3_rsa != NULL); 328 | 329 | // Derivation 1. 330 | unsigned char* derived1_seed = NULL; 331 | size_t derived1_seed_size = 0; 332 | RSA* derived1_rsa; 333 | 334 | _test_decrypt(key, 335 | rotated3_seed, rotated3_seed_size, 336 | &derived1_seed, &derived1_seed_size); 337 | 338 | derived1_rsa = dRSA_deduce_privatekey(BN_num_bits(N), 339 | (unsigned char const*)derived1_seed, 340 | derived1_seed_size); 341 | DOPENSSL_CHECK(derived1_rsa != NULL); 342 | 343 | // Derivation 2. 344 | unsigned char* derived2_seed = NULL; 345 | size_t derived2_seed_size = 0; 346 | RSA* derived2_rsa; 347 | 348 | _test_decrypt(key, 349 | derived1_seed, derived1_seed_size, 350 | &derived2_seed, &derived2_seed_size); 351 | 352 | derived2_rsa = dRSA_deduce_privatekey(BN_num_bits(N), 353 | (unsigned char const*)derived2_seed, 354 | derived2_seed_size); 355 | DOPENSSL_CHECK(derived2_rsa != NULL); 356 | 357 | // Comparisons of the following states. 358 | // 359 | // seed 360 | // ' 361 | // ' 362 | // rotated1_seed 363 | // ' 364 | // ' 365 | // rotated2_seed 366 | // ' 367 | // ' 368 | // rotated3_seed 369 | // ' 370 | // ' 371 | // derived1_seed 372 | // ' 373 | // ' 374 | // derived2_seed 375 | DOPENSSL_CHECK(rotated2_seed_size == derived1_seed_size); 376 | DOPENSSL_CHECK(memcmp(rotated2_seed, derived1_seed, rotated2_seed_size) == 0); 377 | DOPENSSL_CHECK(rotated1_seed_size == derived2_seed_size); 378 | DOPENSSL_CHECK(memcmp(rotated1_seed, derived2_seed, rotated1_seed_size) == 0); 379 | 380 | DOPENSSL_CHECK(dRSA_cmp_privatekey(rotated2_rsa, derived1_rsa) == 0); 381 | DOPENSSL_CHECK(dRSA_cmp_privatekey(rotated1_rsa, derived2_rsa) == 0); 382 | 383 | // Cleaning. 384 | 385 | RSA_free(derived2_rsa); 386 | OPENSSL_free(derived2_seed); 387 | RSA_free(derived1_rsa); 388 | OPENSSL_free(derived1_seed); 389 | RSA_free(rotated3_rsa); 390 | OPENSSL_free(rotated3_seed); 391 | RSA_free(rotated2_rsa); 392 | OPENSSL_free(rotated2_seed); 393 | RSA_free(rotated1_rsa); 394 | OPENSSL_free(rotated1_seed); 395 | 396 | BN_clear_free(N); 397 | 398 | EVP_PKEY_free(key); 399 | 400 | DOPENSSL_CHECK(dRAND_clean() == 1); 401 | } 402 | 403 | /*-----. 404 | | Main | 405 | `-----*/ 406 | 407 | int 408 | main(int argc, 409 | char** argv) 410 | { 411 | test_deduce(); 412 | test_rotate_and_derive(); 413 | 414 | return (0); 415 | } 416 | --------------------------------------------------------------------------------