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