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