1 /* 2 * Copyright 1995-2017 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 <stdio.h> 11 #include "internal/cryptlib.h" 12 #include <openssl/bn.h> 13 #include "dh_locl.h" 14 15 /*- 16 * Check that p and g are suitable enough 17 * 18 * p is odd 19 * 1 < g < p - 1 20 */ 21 int DH_check_params_ex(const DH *dh) 22 { 23 int errflags = 0; 24 25 (void)DH_check_params(dh, &errflags); 26 27 if ((errflags & DH_CHECK_P_NOT_PRIME) != 0) 28 DHerr(DH_F_DH_CHECK_PARAMS_EX, DH_R_CHECK_P_NOT_PRIME); 29 if ((errflags & DH_NOT_SUITABLE_GENERATOR) != 0) 30 DHerr(DH_F_DH_CHECK_PARAMS_EX, DH_R_NOT_SUITABLE_GENERATOR); 31 32 return errflags == 0; 33 } 34 35 int DH_check_params(const DH *dh, int *ret) 36 { 37 int ok = 0; 38 BIGNUM *tmp = NULL; 39 BN_CTX *ctx = NULL; 40 41 *ret = 0; 42 ctx = BN_CTX_new(); 43 if (ctx == NULL) 44 goto err; 45 BN_CTX_start(ctx); 46 tmp = BN_CTX_get(ctx); 47 if (tmp == NULL) 48 goto err; 49 50 if (!BN_is_odd(dh->p)) 51 *ret |= DH_CHECK_P_NOT_PRIME; 52 if (BN_is_negative(dh->g) || BN_is_zero(dh->g) || BN_is_one(dh->g)) 53 *ret |= DH_NOT_SUITABLE_GENERATOR; 54 if (BN_copy(tmp, dh->p) == NULL || !BN_sub_word(tmp, 1)) 55 goto err; 56 if (BN_cmp(dh->g, tmp) >= 0) 57 *ret |= DH_NOT_SUITABLE_GENERATOR; 58 59 ok = 1; 60 err: 61 if (ctx != NULL) { 62 BN_CTX_end(ctx); 63 BN_CTX_free(ctx); 64 } 65 return ok; 66 } 67 68 /*- 69 * Check that p is a safe prime and 70 * if g is 2, 3 or 5, check that it is a suitable generator 71 * where 72 * for 2, p mod 24 == 11 73 * for 3, p mod 12 == 5 74 * for 5, p mod 10 == 3 or 7 75 * should hold. 76 */ 77 int DH_check_ex(const DH *dh) 78 { 79 int errflags = 0; 80 81 (void)DH_check(dh, &errflags); 82 83 if ((errflags & DH_NOT_SUITABLE_GENERATOR) != 0) 84 DHerr(DH_F_DH_CHECK_EX, DH_R_NOT_SUITABLE_GENERATOR); 85 if ((errflags & DH_CHECK_Q_NOT_PRIME) != 0) 86 DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_Q_NOT_PRIME); 87 if ((errflags & DH_CHECK_INVALID_Q_VALUE) != 0) 88 DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_INVALID_Q_VALUE); 89 if ((errflags & DH_CHECK_INVALID_J_VALUE) != 0) 90 DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_INVALID_J_VALUE); 91 if ((errflags & DH_UNABLE_TO_CHECK_GENERATOR) != 0) 92 DHerr(DH_F_DH_CHECK_EX, DH_R_UNABLE_TO_CHECK_GENERATOR); 93 if ((errflags & DH_CHECK_P_NOT_PRIME) != 0) 94 DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_P_NOT_PRIME); 95 if ((errflags & DH_CHECK_P_NOT_SAFE_PRIME) != 0) 96 DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_P_NOT_SAFE_PRIME); 97 98 return errflags == 0; 99 } 100 101 int DH_check(const DH *dh, int *ret) 102 { 103 int ok = 0, r; 104 BN_CTX *ctx = NULL; 105 BN_ULONG l; 106 BIGNUM *t1 = NULL, *t2 = NULL; 107 108 *ret = 0; 109 ctx = BN_CTX_new(); 110 if (ctx == NULL) 111 goto err; 112 BN_CTX_start(ctx); 113 t1 = BN_CTX_get(ctx); 114 t2 = BN_CTX_get(ctx); 115 if (t2 == NULL) 116 goto err; 117 118 if (dh->q) { 119 if (BN_cmp(dh->g, BN_value_one()) <= 0) 120 *ret |= DH_NOT_SUITABLE_GENERATOR; 121 else if (BN_cmp(dh->g, dh->p) >= 0) 122 *ret |= DH_NOT_SUITABLE_GENERATOR; 123 else { 124 /* Check g^q == 1 mod p */ 125 if (!BN_mod_exp(t1, dh->g, dh->q, dh->p, ctx)) 126 goto err; 127 if (!BN_is_one(t1)) 128 *ret |= DH_NOT_SUITABLE_GENERATOR; 129 } 130 r = BN_is_prime_ex(dh->q, BN_prime_checks, ctx, NULL); 131 if (r < 0) 132 goto err; 133 if (!r) 134 *ret |= DH_CHECK_Q_NOT_PRIME; 135 /* Check p == 1 mod q i.e. q divides p - 1 */ 136 if (!BN_div(t1, t2, dh->p, dh->q, ctx)) 137 goto err; 138 if (!BN_is_one(t2)) 139 *ret |= DH_CHECK_INVALID_Q_VALUE; 140 if (dh->j && BN_cmp(dh->j, t1)) 141 *ret |= DH_CHECK_INVALID_J_VALUE; 142 143 } else if (BN_is_word(dh->g, DH_GENERATOR_2)) { 144 l = BN_mod_word(dh->p, 24); 145 if (l == (BN_ULONG)-1) 146 goto err; 147 if (l != 11) 148 *ret |= DH_NOT_SUITABLE_GENERATOR; 149 } else if (BN_is_word(dh->g, DH_GENERATOR_5)) { 150 l = BN_mod_word(dh->p, 10); 151 if (l == (BN_ULONG)-1) 152 goto err; 153 if ((l != 3) && (l != 7)) 154 *ret |= DH_NOT_SUITABLE_GENERATOR; 155 } else 156 *ret |= DH_UNABLE_TO_CHECK_GENERATOR; 157 158 r = BN_is_prime_ex(dh->p, BN_prime_checks, ctx, NULL); 159 if (r < 0) 160 goto err; 161 if (!r) 162 *ret |= DH_CHECK_P_NOT_PRIME; 163 else if (!dh->q) { 164 if (!BN_rshift1(t1, dh->p)) 165 goto err; 166 r = BN_is_prime_ex(t1, BN_prime_checks, ctx, NULL); 167 if (r < 0) 168 goto err; 169 if (!r) 170 *ret |= DH_CHECK_P_NOT_SAFE_PRIME; 171 } 172 ok = 1; 173 err: 174 if (ctx != NULL) { 175 BN_CTX_end(ctx); 176 BN_CTX_free(ctx); 177 } 178 return ok; 179 } 180 181 int DH_check_pub_key_ex(const DH *dh, const BIGNUM *pub_key) 182 { 183 int errflags = 0; 184 185 (void)DH_check(dh, &errflags); 186 187 if ((errflags & DH_CHECK_PUBKEY_TOO_SMALL) != 0) 188 DHerr(DH_F_DH_CHECK_PUB_KEY_EX, DH_R_CHECK_PUBKEY_TOO_SMALL); 189 if ((errflags & DH_CHECK_PUBKEY_TOO_LARGE) != 0) 190 DHerr(DH_F_DH_CHECK_PUB_KEY_EX, DH_R_CHECK_PUBKEY_TOO_LARGE); 191 if ((errflags & DH_CHECK_PUBKEY_INVALID) != 0) 192 DHerr(DH_F_DH_CHECK_PUB_KEY_EX, DH_R_CHECK_PUBKEY_INVALID); 193 194 return errflags == 0; 195 } 196 197 int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret) 198 { 199 int ok = 0; 200 BIGNUM *tmp = NULL; 201 BN_CTX *ctx = NULL; 202 203 *ret = 0; 204 ctx = BN_CTX_new(); 205 if (ctx == NULL) 206 goto err; 207 BN_CTX_start(ctx); 208 tmp = BN_CTX_get(ctx); 209 if (tmp == NULL || !BN_set_word(tmp, 1)) 210 goto err; 211 if (BN_cmp(pub_key, tmp) <= 0) 212 *ret |= DH_CHECK_PUBKEY_TOO_SMALL; 213 if (BN_copy(tmp, dh->p) == NULL || !BN_sub_word(tmp, 1)) 214 goto err; 215 if (BN_cmp(pub_key, tmp) >= 0) 216 *ret |= DH_CHECK_PUBKEY_TOO_LARGE; 217 218 if (dh->q != NULL) { 219 /* Check pub_key^q == 1 mod p */ 220 if (!BN_mod_exp(tmp, pub_key, dh->q, dh->p, ctx)) 221 goto err; 222 if (!BN_is_one(tmp)) 223 *ret |= DH_CHECK_PUBKEY_INVALID; 224 } 225 226 ok = 1; 227 err: 228 if (ctx != NULL) { 229 BN_CTX_end(ctx); 230 BN_CTX_free(ctx); 231 } 232 return ok; 233 } 234