1 /* $OpenBSD: ssl_kex.c,v 1.1 2020/01/30 16:25:09 jsing Exp $ */ 2 /* 3 * Copyright (c) 2020 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/ec.h> 21 #include <openssl/ecdh.h> 22 23 #include "bytestring.h" 24 25 int 26 ssl_kex_generate_ecdhe_ecp(EC_KEY *ecdh, int nid) 27 { 28 EC_GROUP *group; 29 int ret = 0; 30 31 if ((group = EC_GROUP_new_by_curve_name(nid)) == NULL) 32 goto err; 33 34 if (!EC_KEY_set_group(ecdh, group)) 35 goto err; 36 if (!EC_KEY_generate_key(ecdh)) 37 goto err; 38 39 ret = 1; 40 41 err: 42 EC_GROUP_free(group); 43 44 return ret; 45 } 46 47 int 48 ssl_kex_public_ecdhe_ecp(EC_KEY *ecdh, CBB *cbb) 49 { 50 const EC_GROUP *group; 51 const EC_POINT *point; 52 uint8_t *ecp; 53 size_t ecp_len; 54 int ret = 0; 55 56 if ((group = EC_KEY_get0_group(ecdh)) == NULL) 57 goto err; 58 if ((point = EC_KEY_get0_public_key(ecdh)) == NULL) 59 goto err; 60 61 if ((ecp_len = EC_POINT_point2oct(group, point, 62 POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL)) == 0) 63 goto err; 64 if (!CBB_add_space(cbb, &ecp, ecp_len)) 65 goto err; 66 if ((EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, 67 ecp, ecp_len, NULL)) == 0) 68 goto err; 69 70 ret = 1; 71 72 err: 73 return ret; 74 } 75 76 int 77 ssl_kex_peer_public_ecdhe_ecp(EC_KEY *ecdh, int nid, CBS *cbs) 78 { 79 EC_GROUP *group = NULL; 80 EC_POINT *point = NULL; 81 int ret = 0; 82 83 if ((group = EC_GROUP_new_by_curve_name(nid)) == NULL) 84 goto err; 85 86 if (!EC_KEY_set_group(ecdh, group)) 87 goto err; 88 89 if ((point = EC_POINT_new(group)) == NULL) 90 goto err; 91 if (EC_POINT_oct2point(group, point, CBS_data(cbs), CBS_len(cbs), 92 NULL) == 0) 93 goto err; 94 if (!EC_KEY_set_public_key(ecdh, point)) 95 goto err; 96 97 ret = 1; 98 99 err: 100 EC_GROUP_free(group); 101 EC_POINT_free(point); 102 103 return ret; 104 } 105 106 int 107 ssl_kex_derive_ecdhe_ecp(EC_KEY *ecdh, EC_KEY *ecdh_peer, 108 uint8_t **shared_key, size_t *shared_key_len) 109 { 110 const EC_POINT *point; 111 uint8_t *sk = NULL; 112 int sk_len = 0; 113 int ret = 0; 114 115 if (!EC_GROUP_check(EC_KEY_get0_group(ecdh), NULL)) 116 goto err; 117 if (!EC_GROUP_check(EC_KEY_get0_group(ecdh_peer), NULL)) 118 goto err; 119 120 if ((point = EC_KEY_get0_public_key(ecdh_peer)) == NULL) 121 goto err; 122 123 if ((sk_len = ECDH_size(ecdh)) <= 0) 124 goto err; 125 if ((sk = calloc(1, sk_len)) == NULL) 126 goto err; 127 128 if (ECDH_compute_key(sk, sk_len, point, ecdh, NULL) <= 0) 129 goto err; 130 131 *shared_key = sk; 132 *shared_key_len = sk_len; 133 sk = NULL; 134 135 ret = 1; 136 137 err: 138 freezero(sk, sk_len); 139 140 return ret; 141 } 142