1/* 2 * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the OpenSSL license (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10#include <openssl/dh.h> 11 12#include <openssl/bn.h> 13#include <openssl/err.h> 14 15#include "internal.h" 16 17 18int dh_check_params_fast(const DH *dh) { 19 // Most operations scale with p and q. 20 if (BN_is_negative(dh->p) || !BN_is_odd(dh->p) || 21 BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) { 22 OPENSSL_PUT_ERROR(DH, DH_R_INVALID_PARAMETERS); 23 return 0; 24 } 25 26 // q must be bounded by p. 27 if (dh->q != NULL && (BN_is_negative(dh->q) || BN_ucmp(dh->q, dh->p) > 0)) { 28 OPENSSL_PUT_ERROR(DH, DH_R_INVALID_PARAMETERS); 29 return 0; 30 } 31 32 // g must be an element of p's multiplicative group. 33 if (BN_is_negative(dh->g) || BN_is_zero(dh->g) || 34 BN_ucmp(dh->g, dh->p) >= 0) { 35 OPENSSL_PUT_ERROR(DH, DH_R_INVALID_PARAMETERS); 36 return 0; 37 } 38 39 return 1; 40} 41 42int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *out_flags) { 43 *out_flags = 0; 44 if (!dh_check_params_fast(dh)) { 45 return 0; 46 } 47 48 BN_CTX *ctx = BN_CTX_new(); 49 if (ctx == NULL) { 50 return 0; 51 } 52 BN_CTX_start(ctx); 53 54 int ok = 0; 55 56 // Check |pub_key| is greater than 1. 57 if (BN_cmp(pub_key, BN_value_one()) <= 0) { 58 *out_flags |= DH_CHECK_PUBKEY_TOO_SMALL; 59 } 60 61 // Check |pub_key| is less than |dh->p| - 1. 62 BIGNUM *tmp = BN_CTX_get(ctx); 63 if (tmp == NULL || 64 !BN_copy(tmp, dh->p) || 65 !BN_sub_word(tmp, 1)) { 66 goto err; 67 } 68 if (BN_cmp(pub_key, tmp) >= 0) { 69 *out_flags |= DH_CHECK_PUBKEY_TOO_LARGE; 70 } 71 72 if (dh->q != NULL) { 73 // Check |pub_key|^|dh->q| is 1 mod |dh->p|. This is necessary for RFC 5114 74 // groups which are not safe primes but pick a generator on a prime-order 75 // subgroup of size |dh->q|. 76 if (!BN_mod_exp_mont(tmp, pub_key, dh->q, dh->p, ctx, NULL)) { 77 goto err; 78 } 79 if (!BN_is_one(tmp)) { 80 *out_flags |= DH_CHECK_PUBKEY_INVALID; 81 } 82 } 83 84 ok = 1; 85 86err: 87 BN_CTX_end(ctx); 88 BN_CTX_free(ctx); 89 return ok; 90} 91 92 93int DH_check(const DH *dh, int *out_flags) { 94 *out_flags = 0; 95 if (!dh_check_params_fast(dh)) { 96 return 0; 97 } 98 99 // Check that p is a safe prime and if g is 2, 3 or 5, check that it is a 100 // suitable generator where: 101 // for 2, p mod 24 == 11 102 // for 3, p mod 12 == 5 103 // for 5, p mod 10 == 3 or 7 104 // should hold. 105 int ok = 0, r; 106 BN_CTX *ctx = NULL; 107 BN_ULONG l; 108 BIGNUM *t1 = NULL, *t2 = NULL; 109 110 ctx = BN_CTX_new(); 111 if (ctx == NULL) { 112 goto err; 113 } 114 BN_CTX_start(ctx); 115 t1 = BN_CTX_get(ctx); 116 if (t1 == NULL) { 117 goto err; 118 } 119 t2 = BN_CTX_get(ctx); 120 if (t2 == NULL) { 121 goto err; 122 } 123 124 if (dh->q) { 125 if (BN_cmp(dh->g, BN_value_one()) <= 0) { 126 *out_flags |= DH_CHECK_NOT_SUITABLE_GENERATOR; 127 } else if (BN_cmp(dh->g, dh->p) >= 0) { 128 *out_flags |= DH_CHECK_NOT_SUITABLE_GENERATOR; 129 } else { 130 // Check g^q == 1 mod p 131 if (!BN_mod_exp_mont(t1, dh->g, dh->q, dh->p, ctx, NULL)) { 132 goto err; 133 } 134 if (!BN_is_one(t1)) { 135 *out_flags |= DH_CHECK_NOT_SUITABLE_GENERATOR; 136 } 137 } 138 r = BN_is_prime_ex(dh->q, BN_prime_checks_for_validation, ctx, NULL); 139 if (r < 0) { 140 goto err; 141 } 142 if (!r) { 143 *out_flags |= DH_CHECK_Q_NOT_PRIME; 144 } 145 // Check p == 1 mod q i.e. q divides p - 1 146 if (!BN_div(t1, t2, dh->p, dh->q, ctx)) { 147 goto err; 148 } 149 if (!BN_is_one(t2)) { 150 *out_flags |= DH_CHECK_INVALID_Q_VALUE; 151 } 152 } else if (BN_is_word(dh->g, DH_GENERATOR_2)) { 153 l = BN_mod_word(dh->p, 24); 154 if (l == (BN_ULONG)-1) { 155 goto err; 156 } 157 if (l != 11) { 158 *out_flags |= DH_CHECK_NOT_SUITABLE_GENERATOR; 159 } 160 } else if (BN_is_word(dh->g, DH_GENERATOR_5)) { 161 l = BN_mod_word(dh->p, 10); 162 if (l == (BN_ULONG)-1) { 163 goto err; 164 } 165 if (l != 3 && l != 7) { 166 *out_flags |= DH_CHECK_NOT_SUITABLE_GENERATOR; 167 } 168 } else { 169 *out_flags |= DH_CHECK_UNABLE_TO_CHECK_GENERATOR; 170 } 171 172 r = BN_is_prime_ex(dh->p, BN_prime_checks_for_validation, ctx, NULL); 173 if (r < 0) { 174 goto err; 175 } 176 if (!r) { 177 *out_flags |= DH_CHECK_P_NOT_PRIME; 178 } else if (!dh->q) { 179 if (!BN_rshift1(t1, dh->p)) { 180 goto err; 181 } 182 r = BN_is_prime_ex(t1, BN_prime_checks_for_validation, ctx, NULL); 183 if (r < 0) { 184 goto err; 185 } 186 if (!r) { 187 *out_flags |= DH_CHECK_P_NOT_SAFE_PRIME; 188 } 189 } 190 ok = 1; 191 192err: 193 if (ctx != NULL) { 194 BN_CTX_end(ctx); 195 BN_CTX_free(ctx); 196 } 197 return ok; 198} 199