1 /* $OpenBSD: ssl_kex.c,v 1.8 2021/12/04 14:03:22 jsing 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_params->p)) == NULL) 38 goto err; 39 if ((g = BN_dup(dh_params->g)) == 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->p)) <= 0) 111 return 0; 112 if ((dh_g_len = BN_num_bytes(dh->g)) <= 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->p, 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->g, 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->pub_key)) <= 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->pub_key, 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 *invalid_params) 160 { 161 BIGNUM *p = NULL, *g = NULL; 162 CBS dh_p, dh_g; 163 int ret = 0; 164 165 *invalid_params = 0; 166 167 if (!CBS_get_u16_length_prefixed(cbs, &dh_p)) 168 goto err; 169 if (!CBS_get_u16_length_prefixed(cbs, &dh_g)) 170 goto err; 171 172 if ((p = BN_bin2bn(CBS_data(&dh_p), CBS_len(&dh_p), NULL)) == NULL) 173 goto err; 174 if ((g = BN_bin2bn(CBS_data(&dh_g), CBS_len(&dh_g), NULL)) == NULL) 175 goto err; 176 177 if (!DH_set0_pqg(dh, p, NULL, g)) 178 goto err; 179 p = NULL; 180 g = NULL; 181 182 /* XXX - consider calling DH_check(). */ 183 184 if (DH_bits(dh) < DHE_MINIMUM_BITS) 185 *invalid_params = 1; 186 187 ret = 1; 188 189 err: 190 BN_free(p); 191 BN_free(g); 192 193 return ret; 194 } 195 196 int 197 ssl_kex_peer_public_dhe(DH *dh, CBS *cbs, int *invalid_key) 198 { 199 BIGNUM *pub_key = NULL; 200 int check_flags; 201 CBS dh_y; 202 int ret = 0; 203 204 *invalid_key = 0; 205 206 if (!CBS_get_u16_length_prefixed(cbs, &dh_y)) 207 goto err; 208 209 if ((pub_key = BN_bin2bn(CBS_data(&dh_y), CBS_len(&dh_y), 210 NULL)) == NULL) 211 goto err; 212 213 if (!DH_set0_key(dh, pub_key, NULL)) 214 goto err; 215 pub_key = NULL; 216 217 if (!DH_check_pub_key(dh, dh->pub_key, &check_flags)) 218 goto err; 219 if (check_flags != 0) 220 *invalid_key = 1; 221 222 ret = 1; 223 224 err: 225 BN_free(pub_key); 226 227 return ret; 228 } 229 230 int 231 ssl_kex_derive_dhe(DH *dh, DH *dh_peer, 232 uint8_t **shared_key, size_t *shared_key_len) 233 { 234 uint8_t *key = NULL; 235 int key_len = 0; 236 int ret = 0; 237 238 if ((key_len = DH_size(dh)) <= 0) 239 goto err; 240 if ((key = calloc(1, key_len)) == NULL) 241 goto err; 242 243 if ((key_len = DH_compute_key(key, dh_peer->pub_key, dh)) <= 0) 244 goto err; 245 246 *shared_key = key; 247 *shared_key_len = key_len; 248 key = NULL; 249 250 ret = 1; 251 252 err: 253 freezero(key, key_len); 254 255 return ret; 256 } 257 258 int 259 ssl_kex_dummy_ecdhe_x25519(EVP_PKEY *pkey) 260 { 261 EC_GROUP *group = NULL; 262 EC_POINT *point = NULL; 263 EC_KEY *ec_key = NULL; 264 BIGNUM *order = NULL; 265 int ret = 0; 266 267 /* Fudge up an EC_KEY that looks like X25519... */ 268 if ((group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)) == NULL) 269 goto err; 270 if ((point = EC_POINT_new(group)) == NULL) 271 goto err; 272 if ((order = BN_new()) == NULL) 273 goto err; 274 if (!BN_set_bit(order, 252)) 275 goto err; 276 if (!EC_GROUP_set_generator(group, point, order, NULL)) 277 goto err; 278 EC_GROUP_set_curve_name(group, NID_X25519); 279 if ((ec_key = EC_KEY_new()) == NULL) 280 goto err; 281 if (!EC_KEY_set_group(ec_key, group)) 282 goto err; 283 if (!EVP_PKEY_set1_EC_KEY(pkey, ec_key)) 284 goto err; 285 286 ret = 1; 287 288 err: 289 EC_GROUP_free(group); 290 EC_POINT_free(point); 291 EC_KEY_free(ec_key); 292 BN_free(order); 293 294 return ret; 295 } 296 297 int 298 ssl_kex_generate_ecdhe_ecp(EC_KEY *ecdh, int nid) 299 { 300 EC_GROUP *group; 301 int ret = 0; 302 303 if ((group = EC_GROUP_new_by_curve_name(nid)) == NULL) 304 goto err; 305 306 if (!EC_KEY_set_group(ecdh, group)) 307 goto err; 308 if (!EC_KEY_generate_key(ecdh)) 309 goto err; 310 311 ret = 1; 312 313 err: 314 EC_GROUP_free(group); 315 316 return ret; 317 } 318 319 int 320 ssl_kex_public_ecdhe_ecp(EC_KEY *ecdh, CBB *cbb) 321 { 322 const EC_GROUP *group; 323 const EC_POINT *point; 324 uint8_t *ecp; 325 size_t ecp_len; 326 int ret = 0; 327 328 if ((group = EC_KEY_get0_group(ecdh)) == NULL) 329 goto err; 330 if ((point = EC_KEY_get0_public_key(ecdh)) == NULL) 331 goto err; 332 333 if ((ecp_len = EC_POINT_point2oct(group, point, 334 POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL)) == 0) 335 goto err; 336 if (!CBB_add_space(cbb, &ecp, ecp_len)) 337 goto err; 338 if ((EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, 339 ecp, ecp_len, NULL)) == 0) 340 goto err; 341 342 ret = 1; 343 344 err: 345 return ret; 346 } 347 348 int 349 ssl_kex_peer_public_ecdhe_ecp(EC_KEY *ecdh, int nid, CBS *cbs) 350 { 351 EC_GROUP *group = NULL; 352 EC_POINT *point = NULL; 353 int ret = 0; 354 355 if ((group = EC_GROUP_new_by_curve_name(nid)) == NULL) 356 goto err; 357 358 if (!EC_KEY_set_group(ecdh, group)) 359 goto err; 360 361 if ((point = EC_POINT_new(group)) == NULL) 362 goto err; 363 if (EC_POINT_oct2point(group, point, CBS_data(cbs), CBS_len(cbs), 364 NULL) == 0) 365 goto err; 366 if (!EC_KEY_set_public_key(ecdh, point)) 367 goto err; 368 369 ret = 1; 370 371 err: 372 EC_GROUP_free(group); 373 EC_POINT_free(point); 374 375 return ret; 376 } 377 378 int 379 ssl_kex_derive_ecdhe_ecp(EC_KEY *ecdh, EC_KEY *ecdh_peer, 380 uint8_t **shared_key, size_t *shared_key_len) 381 { 382 const EC_POINT *point; 383 uint8_t *key = NULL; 384 int key_len = 0; 385 int ret = 0; 386 387 if (!EC_GROUP_check(EC_KEY_get0_group(ecdh), NULL)) 388 goto err; 389 if (!EC_GROUP_check(EC_KEY_get0_group(ecdh_peer), NULL)) 390 goto err; 391 392 if ((point = EC_KEY_get0_public_key(ecdh_peer)) == NULL) 393 goto err; 394 395 if ((key_len = ECDH_size(ecdh)) <= 0) 396 goto err; 397 if ((key = calloc(1, key_len)) == NULL) 398 goto err; 399 400 if (ECDH_compute_key(key, key_len, point, ecdh, NULL) <= 0) 401 goto err; 402 403 *shared_key = key; 404 *shared_key_len = key_len; 405 key = NULL; 406 407 ret = 1; 408 409 err: 410 freezero(key, key_len); 411 412 return ret; 413 } 414