1d059297112922cabb0c674840589be8db821fd9aAdam Langley/* $OpenBSD: dh.c,v 1.55 2015/01/20 23:14:00 deraadt Exp $ */ 2bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* 3bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Copyright (c) 2000 Niels Provos. All rights reserved. 4bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 5bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Redistribution and use in source and binary forms, with or without 6bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * modification, are permitted provided that the following conditions 7bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * are met: 8bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 1. Redistributions of source code must retain the above copyright 9bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * notice, this list of conditions and the following disclaimer. 10bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 2. Redistributions in binary form must reproduce the above copyright 11bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * notice, this list of conditions and the following disclaimer in the 12bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * documentation and/or other materials provided with the distribution. 13bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 14bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 25bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 26bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "includes.h" 27bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 28d059297112922cabb0c674840589be8db821fd9aAdam Langley#include <sys/param.h> /* MIN */ 29bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 30bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <openssl/bn.h> 31bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <openssl/dh.h> 32bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 33bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <stdarg.h> 34bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <stdio.h> 35bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <stdlib.h> 36bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <string.h> 37d059297112922cabb0c674840589be8db821fd9aAdam Langley#include <limits.h> 38bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 39bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "dh.h" 40bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "pathnames.h" 41bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "log.h" 42bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "misc.h" 43d059297112922cabb0c674840589be8db821fd9aAdam Langley#include "ssherr.h" 44bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 45bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic int 46bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanparse_prime(int linenum, char *line, struct dhgroup *dhg) 47bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 48bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char *cp, *arg; 49bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char *strsize, *gen, *prime; 50bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman const char *errstr = NULL; 51bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman long long n; 52bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 53d059297112922cabb0c674840589be8db821fd9aAdam Langley dhg->p = dhg->g = NULL; 54bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman cp = line; 55bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((arg = strdelim(&cp)) == NULL) 56bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return 0; 57bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Ignore leading whitespace */ 58bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*arg == '\0') 59bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman arg = strdelim(&cp); 60bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (!arg || !*arg || *arg == '#') 61bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return 0; 62bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 63bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* time */ 64bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (cp == NULL || *arg == '\0') 65d059297112922cabb0c674840589be8db821fd9aAdam Langley goto truncated; 66bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman arg = strsep(&cp, " "); /* type */ 67bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (cp == NULL || *arg == '\0') 68d059297112922cabb0c674840589be8db821fd9aAdam Langley goto truncated; 69bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Ensure this is a safe prime */ 70bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman n = strtonum(arg, 0, 5, &errstr); 71d059297112922cabb0c674840589be8db821fd9aAdam Langley if (errstr != NULL || n != MODULI_TYPE_SAFE) { 72d059297112922cabb0c674840589be8db821fd9aAdam Langley error("moduli:%d: type is not %d", linenum, MODULI_TYPE_SAFE); 73bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman goto fail; 74d059297112922cabb0c674840589be8db821fd9aAdam Langley } 75bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman arg = strsep(&cp, " "); /* tests */ 76bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (cp == NULL || *arg == '\0') 77d059297112922cabb0c674840589be8db821fd9aAdam Langley goto truncated; 78bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Ensure prime has been tested and is not composite */ 79bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman n = strtonum(arg, 0, 0x1f, &errstr); 80bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (errstr != NULL || 81d059297112922cabb0c674840589be8db821fd9aAdam Langley (n & MODULI_TESTS_COMPOSITE) || !(n & ~MODULI_TESTS_COMPOSITE)) { 82d059297112922cabb0c674840589be8db821fd9aAdam Langley error("moduli:%d: invalid moduli tests flag", linenum); 83bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman goto fail; 84d059297112922cabb0c674840589be8db821fd9aAdam Langley } 85bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman arg = strsep(&cp, " "); /* tries */ 86bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (cp == NULL || *arg == '\0') 87d059297112922cabb0c674840589be8db821fd9aAdam Langley goto truncated; 88bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman n = strtonum(arg, 0, 1<<30, &errstr); 89d059297112922cabb0c674840589be8db821fd9aAdam Langley if (errstr != NULL || n == 0) { 90d059297112922cabb0c674840589be8db821fd9aAdam Langley error("moduli:%d: invalid primality trial count", linenum); 91bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman goto fail; 92d059297112922cabb0c674840589be8db821fd9aAdam Langley } 93bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman strsize = strsep(&cp, " "); /* size */ 94bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (cp == NULL || *strsize == '\0' || 95bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (dhg->size = (int)strtonum(strsize, 0, 64*1024, &errstr)) == 0 || 96d059297112922cabb0c674840589be8db821fd9aAdam Langley errstr) { 97d059297112922cabb0c674840589be8db821fd9aAdam Langley error("moduli:%d: invalid prime length", linenum); 98bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman goto fail; 99d059297112922cabb0c674840589be8db821fd9aAdam Langley } 100bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* The whole group is one bit larger */ 101bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman dhg->size++; 102bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman gen = strsep(&cp, " "); /* gen */ 103bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (cp == NULL || *gen == '\0') 104d059297112922cabb0c674840589be8db821fd9aAdam Langley goto truncated; 105bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman prime = strsep(&cp, " "); /* prime */ 106d059297112922cabb0c674840589be8db821fd9aAdam Langley if (cp != NULL || *prime == '\0') { 107d059297112922cabb0c674840589be8db821fd9aAdam Langley truncated: 108d059297112922cabb0c674840589be8db821fd9aAdam Langley error("moduli:%d: truncated", linenum); 109bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman goto fail; 110d059297112922cabb0c674840589be8db821fd9aAdam Langley } 111bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 112d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((dhg->g = BN_new()) == NULL || 113d059297112922cabb0c674840589be8db821fd9aAdam Langley (dhg->p = BN_new()) == NULL) { 114d059297112922cabb0c674840589be8db821fd9aAdam Langley error("parse_prime: BN_new failed"); 115d059297112922cabb0c674840589be8db821fd9aAdam Langley goto fail; 116d059297112922cabb0c674840589be8db821fd9aAdam Langley } 117d059297112922cabb0c674840589be8db821fd9aAdam Langley if (BN_hex2bn(&dhg->g, gen) == 0) { 118d059297112922cabb0c674840589be8db821fd9aAdam Langley error("moduli:%d: could not parse generator value", linenum); 119d059297112922cabb0c674840589be8db821fd9aAdam Langley goto fail; 120d059297112922cabb0c674840589be8db821fd9aAdam Langley } 121d059297112922cabb0c674840589be8db821fd9aAdam Langley if (BN_hex2bn(&dhg->p, prime) == 0) { 122d059297112922cabb0c674840589be8db821fd9aAdam Langley error("moduli:%d: could not parse prime value", linenum); 123d059297112922cabb0c674840589be8db821fd9aAdam Langley goto fail; 124d059297112922cabb0c674840589be8db821fd9aAdam Langley } 125d059297112922cabb0c674840589be8db821fd9aAdam Langley if (BN_num_bits(dhg->p) != dhg->size) { 126d059297112922cabb0c674840589be8db821fd9aAdam Langley error("moduli:%d: prime has wrong size: actual %d listed %d", 127d059297112922cabb0c674840589be8db821fd9aAdam Langley linenum, BN_num_bits(dhg->p), dhg->size - 1); 128d059297112922cabb0c674840589be8db821fd9aAdam Langley goto fail; 129d059297112922cabb0c674840589be8db821fd9aAdam Langley } 130d059297112922cabb0c674840589be8db821fd9aAdam Langley if (BN_cmp(dhg->g, BN_value_one()) <= 0) { 131d059297112922cabb0c674840589be8db821fd9aAdam Langley error("moduli:%d: generator is invalid", linenum); 132d059297112922cabb0c674840589be8db821fd9aAdam Langley goto fail; 133d059297112922cabb0c674840589be8db821fd9aAdam Langley } 134d059297112922cabb0c674840589be8db821fd9aAdam Langley return 1; 135bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 136bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fail: 137d059297112922cabb0c674840589be8db821fd9aAdam Langley if (dhg->g != NULL) 138d059297112922cabb0c674840589be8db821fd9aAdam Langley BN_clear_free(dhg->g); 139d059297112922cabb0c674840589be8db821fd9aAdam Langley if (dhg->p != NULL) 140d059297112922cabb0c674840589be8db821fd9aAdam Langley BN_clear_free(dhg->p); 141d059297112922cabb0c674840589be8db821fd9aAdam Langley dhg->g = dhg->p = NULL; 142d059297112922cabb0c674840589be8db821fd9aAdam Langley return 0; 143bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 144bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 145bd77cf78387b72b7b3ea870459077672bf75c3b5Greg HartmanDH * 146bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanchoose_dh(int min, int wantbits, int max) 147bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 148bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman FILE *f; 149bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char line[4096]; 150bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int best, bestcount, which; 151bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int linenum; 152bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman struct dhgroup dhg; 153bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 154bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((f = fopen(_PATH_DH_MODULI, "r")) == NULL && 155bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (f = fopen(_PATH_DH_PRIMES, "r")) == NULL) { 156bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman logit("WARNING: %s does not exist, using fixed modulus", 157bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman _PATH_DH_MODULI); 158bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (dh_new_group14()); 159bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 160bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 161bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman linenum = 0; 162bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman best = bestcount = 0; 163bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman while (fgets(line, sizeof(line), f)) { 164bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman linenum++; 165bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (!parse_prime(linenum, line, &dhg)) 166bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman continue; 167bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman BN_clear_free(dhg.g); 168bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman BN_clear_free(dhg.p); 169bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 170bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (dhg.size > max || dhg.size < min) 171bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman continue; 172bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 173bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((dhg.size > wantbits && dhg.size < best) || 174bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (dhg.size > best && best < wantbits)) { 175bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman best = dhg.size; 176bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman bestcount = 0; 177bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 178bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (dhg.size == best) 179bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman bestcount++; 180bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 181bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman rewind(f); 182bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 183bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (bestcount == 0) { 184bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fclose(f); 185bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman logit("WARNING: no suitable primes in %s", _PATH_DH_PRIMES); 186bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (dh_new_group14()); 187bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 188bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 189bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman linenum = 0; 190bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman which = arc4random_uniform(bestcount); 191bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman while (fgets(line, sizeof(line), f)) { 192bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (!parse_prime(linenum, line, &dhg)) 193bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman continue; 194bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((dhg.size > max || dhg.size < min) || 195bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman dhg.size != best || 196bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman linenum++ != which) { 197bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman BN_clear_free(dhg.g); 198bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman BN_clear_free(dhg.p); 199bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman continue; 200bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 201bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 202bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 203bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fclose(f); 204d059297112922cabb0c674840589be8db821fd9aAdam Langley if (linenum != which+1) { 205d059297112922cabb0c674840589be8db821fd9aAdam Langley logit("WARNING: line %d disappeared in %s, giving up", 206bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman which, _PATH_DH_PRIMES); 207d059297112922cabb0c674840589be8db821fd9aAdam Langley return (dh_new_group14()); 208d059297112922cabb0c674840589be8db821fd9aAdam Langley } 209bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 210bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (dh_new_group(dhg.g, dhg.p)); 211bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 212bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 213bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* diffie-hellman-groupN-sha1 */ 214bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 215bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint 216bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmandh_pub_is_valid(DH *dh, BIGNUM *dh_pub) 217bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 218bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int i; 219bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int n = BN_num_bits(dh_pub); 220bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int bits_set = 0; 221bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman BIGNUM *tmp; 222bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 223bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (dh_pub->neg) { 224bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman logit("invalid public DH value: negative"); 225bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return 0; 226bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 227bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (BN_cmp(dh_pub, BN_value_one()) != 1) { /* pub_exp <= 1 */ 228bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman logit("invalid public DH value: <= 1"); 229bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return 0; 230bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 231bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 232bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((tmp = BN_new()) == NULL) { 233bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman error("%s: BN_new failed", __func__); 234bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return 0; 235bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 236bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (!BN_sub(tmp, dh->p, BN_value_one()) || 237bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman BN_cmp(dh_pub, tmp) != -1) { /* pub_exp > p-2 */ 238bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman BN_clear_free(tmp); 239bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman logit("invalid public DH value: >= p-1"); 240bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return 0; 241bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 242bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman BN_clear_free(tmp); 243bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 244bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (i = 0; i <= n; i++) 245bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (BN_is_bit_set(dh_pub, i)) 246bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman bits_set++; 247bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman debug2("bits set: %d/%d", bits_set, BN_num_bits(dh->p)); 248bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 249bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* if g==2 and bits_set==1 then computing log_g(dh_pub) is trivial */ 250bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (bits_set > 1) 251bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return 1; 252bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 253bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman logit("invalid public DH value (%d/%d)", bits_set, BN_num_bits(dh->p)); 254bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return 0; 255bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 256bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 257d059297112922cabb0c674840589be8db821fd9aAdam Langleyint 258bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmandh_gen_key(DH *dh, int need) 259bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 260d059297112922cabb0c674840589be8db821fd9aAdam Langley int pbits; 261d059297112922cabb0c674840589be8db821fd9aAdam Langley 262d059297112922cabb0c674840589be8db821fd9aAdam Langley if (need < 0 || dh->p == NULL || 263d059297112922cabb0c674840589be8db821fd9aAdam Langley (pbits = BN_num_bits(dh->p)) <= 0 || 264d059297112922cabb0c674840589be8db821fd9aAdam Langley need > INT_MAX / 2 || 2 * need >= pbits) 265d059297112922cabb0c674840589be8db821fd9aAdam Langley return SSH_ERR_INVALID_ARGUMENT; 266d059297112922cabb0c674840589be8db821fd9aAdam Langley#if !defined(OPENSSL_IS_BORINGSSL) 267d059297112922cabb0c674840589be8db821fd9aAdam Langley /* BoringSSL renamed |length| to |priv_length| to better reflect its 268d059297112922cabb0c674840589be8db821fd9aAdam Langley * actual use. Also, BoringSSL recognises common groups and chooses the 269d059297112922cabb0c674840589be8db821fd9aAdam Langley * length of the private exponent accoringly. */ 270d059297112922cabb0c674840589be8db821fd9aAdam Langley dh->length = MIN(need * 2, pbits - 1); 271d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif 272d059297112922cabb0c674840589be8db821fd9aAdam Langley if (DH_generate_key(dh) == 0 || 273d059297112922cabb0c674840589be8db821fd9aAdam Langley !dh_pub_is_valid(dh, dh->pub_key)) { 274d059297112922cabb0c674840589be8db821fd9aAdam Langley BN_clear_free(dh->priv_key); 275d059297112922cabb0c674840589be8db821fd9aAdam Langley return SSH_ERR_LIBCRYPTO_ERROR; 276d059297112922cabb0c674840589be8db821fd9aAdam Langley } 277d059297112922cabb0c674840589be8db821fd9aAdam Langley return 0; 278bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 279bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 280bd77cf78387b72b7b3ea870459077672bf75c3b5Greg HartmanDH * 281bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmandh_new_group_asc(const char *gen, const char *modulus) 282bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 283bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman DH *dh; 284bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 285bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((dh = DH_new()) == NULL) 286d059297112922cabb0c674840589be8db821fd9aAdam Langley return NULL; 287d059297112922cabb0c674840589be8db821fd9aAdam Langley if (BN_hex2bn(&dh->p, modulus) == 0 || 288d059297112922cabb0c674840589be8db821fd9aAdam Langley BN_hex2bn(&dh->g, gen) == 0) { 289d059297112922cabb0c674840589be8db821fd9aAdam Langley DH_free(dh); 290d059297112922cabb0c674840589be8db821fd9aAdam Langley return NULL; 291d059297112922cabb0c674840589be8db821fd9aAdam Langley } 292bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (dh); 293bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 294bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 295bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* 296bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * This just returns the group, we still need to generate the exchange 297bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * value. 298bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 299bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 300bd77cf78387b72b7b3ea870459077672bf75c3b5Greg HartmanDH * 301bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmandh_new_group(BIGNUM *gen, BIGNUM *modulus) 302bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 303bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman DH *dh; 304bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 305bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((dh = DH_new()) == NULL) 306d059297112922cabb0c674840589be8db821fd9aAdam Langley return NULL; 307bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman dh->p = modulus; 308bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman dh->g = gen; 309bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 310bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (dh); 311bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 312bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 313bd77cf78387b72b7b3ea870459077672bf75c3b5Greg HartmanDH * 314bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmandh_new_group1(void) 315bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 316bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman static char *gen = "2", *group1 = 317bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1" 318bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD" 319bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245" 320bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED" 321bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381" 322bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman "FFFFFFFF" "FFFFFFFF"; 323bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 324bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (dh_new_group_asc(gen, group1)); 325bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 326bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 327bd77cf78387b72b7b3ea870459077672bf75c3b5Greg HartmanDH * 328bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmandh_new_group14(void) 329bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 330bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman static char *gen = "2", *group14 = 331bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1" 332bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD" 333bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245" 334bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED" 335bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE45B3D" 336bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman "C2007CB8" "A163BF05" "98DA4836" "1C55D39A" "69163FA8" "FD24CF5F" 337bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman "83655D23" "DCA3AD96" "1C62F356" "208552BB" "9ED52907" "7096966D" 338bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman "670C354E" "4ABC9804" "F1746C08" "CA18217C" "32905E46" "2E36CE3B" 339bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman "E39E772C" "180E8603" "9B2783A2" "EC07A28F" "B5C55DF0" "6F4C52C9" 340bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman "DE2BCBF6" "95581718" "3995497C" "EA956AE5" "15D22618" "98FA0510" 341bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman "15728E5A" "8AACAA68" "FFFFFFFF" "FFFFFFFF"; 342bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 343bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (dh_new_group_asc(gen, group14)); 344bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 345bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 346bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* 347bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Estimates the group order for a Diffie-Hellman group that has an 348d059297112922cabb0c674840589be8db821fd9aAdam Langley * attack complexity approximately the same as O(2**bits). 349d059297112922cabb0c674840589be8db821fd9aAdam Langley * Values from NIST Special Publication 800-57: Recommendation for Key 350d059297112922cabb0c674840589be8db821fd9aAdam Langley * Management Part 1 (rev 3) limited by the recommended maximum value 351d059297112922cabb0c674840589be8db821fd9aAdam Langley * from RFC4419 section 3. 352bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 353bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 354d059297112922cabb0c674840589be8db821fd9aAdam Langleyu_int 355bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmandh_estimate(int bits) 356bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 357d059297112922cabb0c674840589be8db821fd9aAdam Langley if (bits <= 112) 358d059297112922cabb0c674840589be8db821fd9aAdam Langley return 2048; 359bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (bits <= 128) 360d059297112922cabb0c674840589be8db821fd9aAdam Langley return 3072; 361bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (bits <= 192) 362d059297112922cabb0c674840589be8db821fd9aAdam Langley return 7680; 363d059297112922cabb0c674840589be8db821fd9aAdam Langley return 8192; 364bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 365