1 1.4 christos /* $NetBSD: qsafe.c,v 1.4 2018/02/06 19:32:49 christos Exp $ */ 2 1.1 elad 3 1.1 elad /*- 4 1.1 elad * Copyright 1994 Phil Karn <karn (at) qualcomm.com> 5 1.1 elad * Copyright 1996-1998, 2003 William Allen206 Simpson <wsimpson (at) greendragon.com> 6 1.1 elad * Copyright 2000 Niels Provos <provos (at) citi.umich.edu> 7 1.1 elad * All rights reserved. 8 1.1 elad * 9 1.1 elad * Redistribution and use in source and binary forms, with or without 10 1.1 elad * modification, are permitted provided that the following conditions 11 1.1 elad * are met: 12 1.1 elad * 1. Redistributions of source code must retain the above copyright 13 1.1 elad * notice, this list of conditions and the following disclaimer. 14 1.1 elad * 2. Redistributions in binary form must reproduce the above copyright 15 1.1 elad * notice, this list of conditions and the following disclaimer in the 16 1.1 elad * documentation and/or other materials provided with the distribution. 17 1.1 elad * 18 1.1 elad * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 1.1 elad * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 1.1 elad * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 1.1 elad * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 1.1 elad * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 1.1 elad * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 1.1 elad * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 1.1 elad * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 1.1 elad * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 1.1 elad * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 1.1 elad */ 29 1.1 elad 30 1.1 elad /* 31 1.1 elad * Test probable "safe" primes, 32 1.1 elad * 33 1.1 elad * suitable for use as Diffie-Hellman moduli; 34 1.1 elad * that is, where q = (p-1)/2 is also prime. 35 1.1 elad * 36 1.1 elad * This is the second of two steps. 37 1.1 elad * This step is processor intensive. 38 1.1 elad * 39 1.1 elad * 1996 May William Allen Simpson 40 1.1 elad * extracted from earlier code by Phil Karn, April 1994. 41 1.1 elad * read large prime candidates list (q), 42 1.1 elad * and check prime probability of (p). 43 1.1 elad * 1998 May William Allen Simpson 44 1.1 elad * parameterized. 45 1.1 elad * optionally limit to a single generator. 46 1.1 elad * 2000 Dec Niels Provos 47 1.1 elad * convert from GMP to openssl BN. 48 1.1 elad * 2003 Jun William Allen Simpson 49 1.1 elad * change outfile definition slightly to match openssh mistake. 50 1.1 elad * move common file i/o to own file for better documentation. 51 1.1 elad * redo debugprint again. 52 1.1 elad */ 53 1.1 elad 54 1.1 elad #include <stdlib.h> 55 1.1 elad #include <stdio.h> 56 1.1 elad #include <string.h> 57 1.1 elad #include <time.h> 58 1.1 elad #include <openssl/bn.h> 59 1.1 elad #include "qfile.h" 60 1.1 elad 61 1.1 elad /* define DEBUGPRINT 1 */ 62 1.1 elad #define TRIAL_MINIMUM (4) 63 1.1 elad 64 1.3 joerg __dead static void usage(void); 65 1.1 elad 66 1.1 elad /* 67 1.1 elad * perform a Miller-Rabin primality test 68 1.1 elad * on the list of candidates 69 1.1 elad * (checking both q and p) 70 1.1 elad * from standard input. 71 1.1 elad * The result is a list of so-call "safe" primes 72 1.1 elad * to standard output, 73 1.1 elad */ 74 1.1 elad int 75 1.1 elad main(int argc, char *argv[]) 76 1.1 elad { 77 1.1 elad BIGNUM *q, *p, *a; 78 1.1 elad BN_CTX *ctx; 79 1.1 elad char *cp; 80 1.1 elad char *lp; 81 1.1 elad uint32_t count_in = 0; 82 1.1 elad uint32_t count_out = 0; 83 1.1 elad uint32_t count_possible = 0; 84 1.1 elad uint32_t generator_known; 85 1.1 elad uint32_t generator_wanted = 0; 86 1.1 elad uint32_t in_tests; 87 1.1 elad uint32_t in_tries; 88 1.1 elad uint32_t in_type; 89 1.1 elad uint32_t in_size; 90 1.1 elad int trials; 91 1.1 elad time_t time_start; 92 1.1 elad time_t time_stop; 93 1.1 elad 94 1.1 elad setprogname(argv[0]); 95 1.1 elad 96 1.1 elad if (argc < 2) { 97 1.1 elad usage(); 98 1.1 elad } 99 1.1 elad 100 1.1 elad if ((trials = strtoul(argv[1], NULL, 10)) < TRIAL_MINIMUM) { 101 1.1 elad trials = TRIAL_MINIMUM; 102 1.1 elad } 103 1.1 elad 104 1.1 elad if (argc > 2) { 105 1.1 elad generator_wanted = strtoul(argv[2], NULL, 16); 106 1.1 elad } 107 1.1 elad 108 1.1 elad time(&time_start); 109 1.1 elad 110 1.1 elad p = BN_new(); 111 1.1 elad q = BN_new(); 112 1.1 elad ctx = BN_CTX_new(); 113 1.1 elad 114 1.1 elad (void)fprintf(stderr, 115 1.1 elad "%.24s Final %d Miller-Rabin trials (%x generator)\n", 116 1.1 elad ctime(&time_start), trials, generator_wanted); 117 1.1 elad 118 1.1 elad lp = (char *) malloc((unsigned long) QLINESIZE + 1); 119 1.1 elad 120 1.1 elad while (fgets(lp, QLINESIZE, stdin) != NULL) { 121 1.1 elad size_t ll = strlen(lp); 122 1.1 elad 123 1.1 elad count_in++; 124 1.1 elad 125 1.1 elad if (ll < 14 || *lp == '!' || *lp == '#') { 126 1.1 elad #ifdef DEBUGPRINT 127 1.1 elad (void)fprintf(stderr, "%10lu: comment or short" 128 1.1 elad " line\n", count_in); 129 1.1 elad #endif 130 1.1 elad continue; 131 1.1 elad } 132 1.1 elad 133 1.1 elad /* time */ 134 1.1 elad cp = &lp[14]; /* (skip) */ 135 1.1 elad 136 1.1 elad /* type */ 137 1.1 elad in_type = strtoul(cp, &cp, 10); 138 1.1 elad 139 1.1 elad /* tests */ 140 1.1 elad in_tests = strtoul(cp, &cp, 10); 141 1.1 elad if (in_tests & QTEST_COMPOSITE) { 142 1.1 elad #ifdef DEBUGPRINT 143 1.1 elad (void)fprintf(stderr, "%10lu: known composite\n", 144 1.1 elad count_in); 145 1.1 elad #endif 146 1.1 elad continue; 147 1.1 elad } 148 1.1 elad 149 1.1 elad /* tries */ 150 1.1 elad in_tries = (uint32_t) strtoul(cp, &cp, 10); 151 1.1 elad 152 1.1 elad /* size (most significant bit) */ 153 1.1 elad in_size = (uint32_t) strtoul(cp, &cp, 10); 154 1.1 elad 155 1.1 elad /* generator (hex) */ 156 1.1 elad generator_known = (uint32_t) strtoul(cp, &cp, 16); 157 1.1 elad 158 1.1 elad /* Skip white space */ 159 1.1 elad cp += strspn(cp, " "); 160 1.1 elad 161 1.1 elad /* modulus (hex) */ 162 1.1 elad switch (in_type) { 163 1.1 elad case QTYPE_SOPHIE_GERMAINE: 164 1.1 elad #ifdef DEBUGPRINT 165 1.1 elad (void)fprintf(stderr, "%10lu: (%lu) " 166 1.1 elad "Sophie-Germaine\n", count_in, 167 1.1 elad in_type); 168 1.1 elad #endif 169 1.1 elad 170 1.1 elad a = q; 171 1.1 elad BN_hex2bn(&a, cp); 172 1.1 elad /* p = 2*q + 1 */ 173 1.1 elad BN_lshift(p, q, 1); 174 1.1 elad BN_add_word(p, 1UL); 175 1.1 elad in_size += 1; 176 1.1 elad generator_known = 0; 177 1.1 elad 178 1.1 elad break; 179 1.1 elad 180 1.1 elad default: 181 1.1 elad #ifdef DEBUGPRINT 182 1.1 elad (void)fprintf(stderr, "%10lu: (%lu)\n", 183 1.1 elad count_in, in_type); 184 1.1 elad #endif 185 1.1 elad a = p; 186 1.1 elad BN_hex2bn(&a, cp); 187 1.1 elad /* q = (p-1) / 2 */ 188 1.1 elad BN_rshift(q, p, 1); 189 1.1 elad 190 1.1 elad break; 191 1.1 elad } 192 1.1 elad 193 1.1 elad /* 194 1.1 elad * due to earlier inconsistencies in interpretation, check the 195 1.1 elad * proposed bit size. 196 1.1 elad */ 197 1.2 lukem if ((uint32_t)BN_num_bits(p) != (in_size + 1)) { 198 1.1 elad #ifdef DEBUGPRINT 199 1.1 elad (void)fprintf(stderr, "%10lu: bit size %ul " 200 1.1 elad "mismatch\n", count_in, in_size); 201 1.1 elad #endif 202 1.1 elad continue; 203 1.1 elad } 204 1.1 elad 205 1.1 elad if (in_size < QSIZE_MINIMUM) { 206 1.1 elad #ifdef DEBUGPRINT 207 1.1 elad (void)fprintf(stderr, "%10lu: bit size %ul " 208 1.1 elad "too short\n", count_in, in_size); 209 1.1 elad #endif 210 1.1 elad continue; 211 1.1 elad } 212 1.1 elad 213 1.1 elad if (in_tests & QTEST_MILLER_RABIN) 214 1.1 elad in_tries += trials; 215 1.1 elad else 216 1.1 elad in_tries = trials; 217 1.1 elad 218 1.1 elad /* 219 1.1 elad * guess unknown generator 220 1.1 elad */ 221 1.1 elad if (generator_known == 0) { 222 1.1 elad if (BN_mod_word(p, 24UL) == 11) 223 1.1 elad generator_known = 2; 224 1.1 elad else if (BN_mod_word(p, 12UL) == 5) 225 1.1 elad generator_known = 3; 226 1.1 elad else { 227 1.1 elad BN_ULONG r = BN_mod_word(p, 10UL); 228 1.1 elad 229 1.1 elad if (r == 3 || r == 7) { 230 1.1 elad generator_known = 5; 231 1.1 elad } 232 1.1 elad } 233 1.1 elad } 234 1.1 elad 235 1.1 elad /* 236 1.1 elad * skip tests when desired generator doesn't match 237 1.1 elad */ 238 1.1 elad if (generator_wanted > 0 && 239 1.1 elad generator_wanted != generator_known) { 240 1.1 elad #ifdef DEBUGPRINT 241 1.1 elad (void)fprintf(stderr, 242 1.1 elad "%10lu: generator %ld != %ld\n", 243 1.1 elad count_in, generator_known, generator_wanted); 244 1.1 elad #endif 245 1.1 elad continue; 246 1.1 elad } 247 1.1 elad 248 1.1 elad count_possible++; 249 1.1 elad 250 1.1 elad /* 251 1.1 elad * The (1/4)^N performance bound on Miller-Rabin is extremely 252 1.1 elad * pessimistic, so don't spend a lot of time really verifying 253 1.1 elad * that q is prime until after we know that p is also prime. A 254 1.1 elad * single pass will weed out the vast majority of composite 255 1.1 elad * q's. 256 1.1 elad */ 257 1.4 christos if (BN_is_prime_ex(q, 1, ctx, NULL) <= 0) { 258 1.1 elad #ifdef DEBUGPRINT 259 1.1 elad (void)fprintf(stderr, "%10lu: q failed first " 260 1.1 elad "possible prime test\n", count_in); 261 1.1 elad #endif 262 1.1 elad continue; 263 1.1 elad } 264 1.1 elad 265 1.1 elad /* 266 1.1 elad * q is possibly prime, so go ahead and really make sure that 267 1.1 elad * p is prime. If it is, then we can go back and do the same 268 1.1 elad * for q. If p is composite, chances are that will show up on 269 1.1 elad * the first Rabin-Miller iteration so it doesn't hurt to 270 1.1 elad * specify a high iteration count. 271 1.1 elad */ 272 1.4 christos if (!BN_is_prime_ex(p, trials, ctx, NULL)) { 273 1.1 elad #ifdef DEBUGPRINT 274 1.1 elad (void)fprintf(stderr, "%10lu: p is not prime\n", 275 1.1 elad count_in); 276 1.1 elad #endif 277 1.1 elad continue; 278 1.1 elad } 279 1.1 elad 280 1.1 elad #ifdef DEBUGPRINT 281 1.1 elad (void)fprintf(stderr, "%10lu: p is almost certainly " 282 1.1 elad "prime\n", count_in); 283 1.1 elad #endif 284 1.1 elad 285 1.1 elad /* recheck q more rigorously */ 286 1.4 christos if (!BN_is_prime_ex(q, trials - 1, ctx, NULL)) { 287 1.1 elad #ifdef DEBUGPRINT 288 1.1 elad (void)fprintf(stderr, "%10lu: q is not prime\n", 289 1.1 elad count_in); 290 1.1 elad #endif 291 1.1 elad continue; 292 1.1 elad } 293 1.1 elad #ifdef DEBUGPRINT 294 1.1 elad fprintf(stderr, "%10lu: q is almost certainly prime\n", 295 1.1 elad count_in); 296 1.1 elad #endif 297 1.1 elad if (0 > qfileout(stdout, 298 1.1 elad QTYPE_SAFE, 299 1.1 elad (in_tests | QTEST_MILLER_RABIN), 300 1.1 elad in_tries, 301 1.1 elad in_size, 302 1.1 elad generator_known, 303 1.1 elad p)) { 304 1.1 elad break; 305 1.1 elad } 306 1.1 elad count_out++; 307 1.1 elad #ifdef DEBUGPRINT 308 1.1 elad fflush(stderr); 309 1.1 elad fflush(stdout); 310 1.1 elad #endif 311 1.1 elad } 312 1.1 elad 313 1.1 elad time(&time_stop); 314 1.1 elad free(lp); 315 1.1 elad BN_free(p); 316 1.1 elad BN_free(q); 317 1.1 elad BN_CTX_free(ctx); 318 1.1 elad fflush(stdout); /* fclose(stdout); */ 319 1.1 elad /* fclose(stdin); */ 320 1.1 elad (void)fprintf(stderr, 321 1.1 elad "%.24s Found %u safe primes of %u candidates in %lu seconds\n", 322 1.1 elad ctime(&time_stop), count_out, count_possible, 323 1.1 elad (long) (time_stop - time_start)); 324 1.1 elad 325 1.1 elad return (0); 326 1.1 elad } 327 1.1 elad 328 1.1 elad static void 329 1.1 elad usage(void) 330 1.1 elad { 331 1.1 elad (void)fprintf(stderr, "Usage: %s <trials> [generator]\n", 332 1.1 elad getprogname()); 333 1.1 elad exit(1); 334 1.1 elad } 335