1 /* $OpenBSD: ssl_kex.c,v 1.10 2022/01/14 09:11:22 tb Exp $ */ 2 /* 3 * Copyright (c) 2020, 2021 Joel Sing <jsing@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <stdlib.h> 19 20 #include <openssl/bn.h> 21 #include <openssl/dh.h> 22 #include <openssl/ec.h> 23 #include <openssl/ecdh.h> 24 #include <openssl/evp.h> 25 #include <openssl/objects.h> 26 27 #include "bytestring.h" 28 29 #define DHE_MINIMUM_BITS 1024 30 31 int 32 ssl_kex_generate_dhe(DH *dh, DH *dh_params) 33 { 34 BIGNUM *p = NULL, *g = NULL; 35 int ret = 0; 36 37 if ((p = BN_dup(DH_get0_p(dh_params))) == NULL) 38 goto err; 39 if ((g = BN_dup(DH_get0_g(dh_params))) == NULL) 40 goto err; 41 42 if (!DH_set0_pqg(dh, p, NULL, g)) 43 goto err; 44 p = NULL; 45 g = NULL; 46 47 if (!DH_generate_key(dh)) 48 goto err; 49 50 ret = 1; 51 52 err: 53 BN_free(p); 54 BN_free(g); 55 56 return ret; 57 } 58 59 int 60 ssl_kex_generate_dhe_params_auto(DH *dh, size_t key_bits) 61 { 62 BIGNUM *p = NULL, *g = NULL; 63 int ret = 0; 64 65 if (key_bits >= 8192) 66 p = get_rfc3526_prime_8192(NULL); 67 else if (key_bits >= 4096) 68 p = get_rfc3526_prime_4096(NULL); 69 else if (key_bits >= 3072) 70 p = get_rfc3526_prime_3072(NULL); 71 else if (key_bits >= 2048) 72 p = get_rfc3526_prime_2048(NULL); 73 else if (key_bits >= 1536) 74 p = get_rfc3526_prime_1536(NULL); 75 else 76 p = get_rfc2409_prime_1024(NULL); 77 78 if (p == NULL) 79 goto err; 80 81 if ((g = BN_new()) == NULL) 82 goto err; 83 if (!BN_set_word(g, 2)) 84 goto err; 85 86 if (!DH_set0_pqg(dh, p, NULL, g)) 87 goto err; 88 p = NULL; 89 g = NULL; 90 91 if (!DH_generate_key(dh)) 92 goto err; 93 94 ret = 1; 95 96 err: 97 BN_free(p); 98 BN_free(g); 99 100 return ret; 101 } 102 103 int 104 ssl_kex_params_dhe(DH *dh, CBB *cbb) 105 { 106 int dh_p_len, dh_g_len; 107 CBB dh_p, dh_g; 108 uint8_t *data; 109 110 if ((dh_p_len = BN_num_bytes(DH_get0_p(dh))) <= 0) 111 return 0; 112 if ((dh_g_len = BN_num_bytes(DH_get0_g(dh))) <= 0) 113 return 0; 114 115 if (!CBB_add_u16_length_prefixed(cbb, &dh_p)) 116 return 0; 117 if (!CBB_add_space(&dh_p, &data, dh_p_len)) 118 return 0; 119 if (BN_bn2bin(DH_get0_p(dh), data) != dh_p_len) 120 return 0; 121 122 if (!CBB_add_u16_length_prefixed(cbb, &dh_g)) 123 return 0; 124 if (!CBB_add_space(&dh_g, &data, dh_g_len)) 125 return 0; 126 if (BN_bn2bin(DH_get0_g(dh), data) != dh_g_len) 127 return 0; 128 129 if (!CBB_flush(cbb)) 130 return 0; 131 132 return 1; 133 } 134 135 int 136 ssl_kex_public_dhe(DH *dh, CBB *cbb) 137 { 138 uint8_t *data; 139 int dh_y_len; 140 CBB dh_y; 141 142 if ((dh_y_len = BN_num_bytes(DH_get0_pub_key(dh))) <= 0) 143 return 0; 144 145 if (!CBB_add_u16_length_prefixed(cbb, &dh_y)) 146 return 0; 147 if (!CBB_add_space(&dh_y, &data, dh_y_len)) 148 return 0; 149 if (BN_bn2bin(DH_get0_pub_key(dh), data) != dh_y_len) 150 return 0; 151 152 if (!CBB_flush(cbb)) 153 return 0; 154 155 return 1; 156 } 157 158 int 159 ssl_kex_peer_params_dhe(DH *dh, CBS *cbs, int *decode_error, 160 int *invalid_params) 161 { 162 BIGNUM *p = NULL, *g = NULL; 163 CBS dh_p, dh_g; 164 int ret = 0; 165 166 *decode_error = 0; 167 *invalid_params = 0; 168 169 if (!CBS_get_u16_length_prefixed(cbs, &dh_p)) { 170 *decode_error = 1; 171 goto err; 172 } 173 if (!CBS_get_u16_length_prefixed(cbs, &dh_g)) { 174 *decode_error = 1; 175 goto err; 176 } 177 178 if ((p = BN_bin2bn(CBS_data(&dh_p), CBS_len(&dh_p), NULL)) == NULL) 179 goto err; 180 if ((g = BN_bin2bn(CBS_data(&dh_g), CBS_len(&dh_g), NULL)) == NULL) 181 goto err; 182 183 if (!DH_set0_pqg(dh, p, NULL, g)) 184 goto err; 185 p = NULL; 186 g = NULL; 187 188 /* XXX - consider calling DH_check(). */ 189 190 if (DH_bits(dh) < DHE_MINIMUM_BITS) 191 *invalid_params = 1; 192 193 ret = 1; 194 195 err: 196 BN_free(p); 197 BN_free(g); 198 199 return ret; 200 } 201 202 int 203 ssl_kex_peer_public_dhe(DH *dh, CBS *cbs, int *decode_error, 204 int *invalid_key) 205 { 206 BIGNUM *pub_key = NULL; 207 int check_flags; 208 CBS dh_y; 209 int ret = 0; 210 211 *decode_error = 0; 212 *invalid_key = 0; 213 214 if (!CBS_get_u16_length_prefixed(cbs, &dh_y)) { 215 *decode_error = 1; 216 goto err; 217 } 218 219 if ((pub_key = BN_bin2bn(CBS_data(&dh_y), CBS_len(&dh_y), 220 NULL)) == NULL) 221 goto err; 222 223 if (!DH_set0_key(dh, pub_key, NULL)) 224 goto err; 225 pub_key = NULL; 226 227 if (!DH_check_pub_key(dh, DH_get0_pub_key(dh), &check_flags)) 228 goto err; 229 if (check_flags != 0) 230 *invalid_key = 1; 231 232 ret = 1; 233 234 err: 235 BN_free(pub_key); 236 237 return ret; 238 } 239 240 int 241 ssl_kex_derive_dhe(DH *dh, DH *dh_peer, 242 uint8_t **shared_key, size_t *shared_key_len) 243 { 244 uint8_t *key = NULL; 245 int key_len = 0; 246 int ret = 0; 247 248 if ((key_len = DH_size(dh)) <= 0) 249 goto err; 250 if ((key = calloc(1, key_len)) == NULL) 251 goto err; 252 253 if ((key_len = DH_compute_key(key, DH_get0_pub_key(dh_peer), dh)) <= 0) 254 goto err; 255 256 *shared_key = key; 257 *shared_key_len = key_len; 258 key = NULL; 259 260 ret = 1; 261 262 err: 263 freezero(key, key_len); 264 265 return ret; 266 } 267 268 int 269 ssl_kex_dummy_ecdhe_x25519(EVP_PKEY *pkey) 270 { 271 EC_GROUP *group = NULL; 272 EC_POINT *point = NULL; 273 EC_KEY *ec_key = NULL; 274 BIGNUM *order = NULL; 275 int ret = 0; 276 277 /* Fudge up an EC_KEY that looks like X25519... */ 278 if ((group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)) == NULL) 279 goto err; 280 if ((point = EC_POINT_new(group)) == NULL) 281 goto err; 282 if ((order = BN_new()) == NULL) 283 goto err; 284 if (!BN_set_bit(order, 252)) 285 goto err; 286 if (!EC_GROUP_set_generator(group, point, order, NULL)) 287 goto err; 288 EC_GROUP_set_curve_name(group, NID_X25519); 289 if ((ec_key = EC_KEY_new()) == NULL) 290 goto err; 291 if (!EC_KEY_set_group(ec_key, group)) 292 goto err; 293 if (!EVP_PKEY_set1_EC_KEY(pkey, ec_key)) 294 goto err; 295 296 ret = 1; 297 298 err: 299 EC_GROUP_free(group); 300 EC_POINT_free(point); 301 EC_KEY_free(ec_key); 302 BN_free(order); 303 304 return ret; 305 } 306 307 int 308 ssl_kex_generate_ecdhe_ecp(EC_KEY *ecdh, int nid) 309 { 310 EC_GROUP *group; 311 int ret = 0; 312 313 if ((group = EC_GROUP_new_by_curve_name(nid)) == NULL) 314 goto err; 315 316 if (!EC_KEY_set_group(ecdh, group)) 317 goto err; 318 if (!EC_KEY_generate_key(ecdh)) 319 goto err; 320 321 ret = 1; 322 323 err: 324 EC_GROUP_free(group); 325 326 return ret; 327 } 328 329 int 330 ssl_kex_public_ecdhe_ecp(EC_KEY *ecdh, CBB *cbb) 331 { 332 const EC_GROUP *group; 333 const EC_POINT *point; 334 uint8_t *ecp; 335 size_t ecp_len; 336 int ret = 0; 337 338 if ((group = EC_KEY_get0_group(ecdh)) == NULL) 339 goto err; 340 if ((point = EC_KEY_get0_public_key(ecdh)) == NULL) 341 goto err; 342 343 if ((ecp_len = EC_POINT_point2oct(group, point, 344 POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL)) == 0) 345 goto err; 346 if (!CBB_add_space(cbb, &ecp, ecp_len)) 347 goto err; 348 if ((EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, 349 ecp, ecp_len, NULL)) == 0) 350 goto err; 351 352 ret = 1; 353 354 err: 355 return ret; 356 } 357 358 int 359 ssl_kex_peer_public_ecdhe_ecp(EC_KEY *ecdh, int nid, CBS *cbs) 360 { 361 EC_GROUP *group = NULL; 362 EC_POINT *point = NULL; 363 int ret = 0; 364 365 if ((group = EC_GROUP_new_by_curve_name(nid)) == NULL) 366 goto err; 367 368 if (!EC_KEY_set_group(ecdh, group)) 369 goto err; 370 371 if ((point = EC_POINT_new(group)) == NULL) 372 goto err; 373 if (EC_POINT_oct2point(group, point, CBS_data(cbs), CBS_len(cbs), 374 NULL) == 0) 375 goto err; 376 if (!EC_KEY_set_public_key(ecdh, point)) 377 goto err; 378 379 ret = 1; 380 381 err: 382 EC_GROUP_free(group); 383 EC_POINT_free(point); 384 385 return ret; 386 } 387 388 int 389 ssl_kex_derive_ecdhe_ecp(EC_KEY *ecdh, EC_KEY *ecdh_peer, 390 uint8_t **shared_key, size_t *shared_key_len) 391 { 392 const EC_POINT *point; 393 uint8_t *key = NULL; 394 int key_len = 0; 395 int ret = 0; 396 397 if (!EC_GROUP_check(EC_KEY_get0_group(ecdh), NULL)) 398 goto err; 399 if (!EC_GROUP_check(EC_KEY_get0_group(ecdh_peer), NULL)) 400 goto err; 401 402 if ((point = EC_KEY_get0_public_key(ecdh_peer)) == NULL) 403 goto err; 404 405 if ((key_len = ECDH_size(ecdh)) <= 0) 406 goto err; 407 if ((key = calloc(1, key_len)) == NULL) 408 goto err; 409 410 if (ECDH_compute_key(key, key_len, point, ecdh, NULL) <= 0) 411 goto err; 412 413 *shared_key = key; 414 *shared_key_len = key_len; 415 key = NULL; 416 417 ret = 1; 418 419 err: 420 freezero(key, key_len); 421 422 return ret; 423 } 424