1 /* Copyright (c) 2015, Google Inc.
2  *
3  * Permission to use, copy, modify, and/or distribute this software for any
4  * purpose with or without fee is hereby granted, provided that the above
5  * copyright notice and this permission notice appear in all copies.
6  *
7  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14 
15 #include <openssl/ssl.h>
16 
17 #include <assert.h>
18 #include <string.h>
19 
20 #include <openssl/bn.h>
21 #include <openssl/bytestring.h>
22 #include <openssl/curve25519.h>
23 #include <openssl/ec.h>
24 #include <openssl/err.h>
25 #include <openssl/mem.h>
26 #include <openssl/newhope.h>
27 #include <openssl/nid.h>
28 
29 #include "internal.h"
30 
31 
32 /* |EC_POINT| implementation. */
33 
ssl_ec_point_cleanup(SSL_ECDH_CTX * ctx)34 static void ssl_ec_point_cleanup(SSL_ECDH_CTX *ctx) {
35   BIGNUM *private_key = (BIGNUM *)ctx->data;
36   BN_clear_free(private_key);
37 }
38 
ssl_ec_point_offer(SSL_ECDH_CTX * ctx,CBB * out)39 static int ssl_ec_point_offer(SSL_ECDH_CTX *ctx, CBB *out) {
40   assert(ctx->data == NULL);
41   BIGNUM *private_key = BN_new();
42   if (private_key == NULL) {
43     return 0;
44   }
45   ctx->data = private_key;
46 
47   /* Set up a shared |BN_CTX| for all operations. */
48   BN_CTX *bn_ctx = BN_CTX_new();
49   if (bn_ctx == NULL) {
50     return 0;
51   }
52   BN_CTX_start(bn_ctx);
53 
54   int ret = 0;
55   EC_POINT *public_key = NULL;
56   EC_GROUP *group = EC_GROUP_new_by_curve_name(ctx->method->nid);
57   if (group == NULL) {
58     goto err;
59   }
60 
61   /* Generate a private key. */
62   const BIGNUM *order = EC_GROUP_get0_order(group);
63   do {
64     if (!BN_rand_range(private_key, order)) {
65       goto err;
66     }
67   } while (BN_is_zero(private_key));
68 
69   /* Compute the corresponding public key and serialize it. */
70   public_key = EC_POINT_new(group);
71   if (public_key == NULL ||
72       !EC_POINT_mul(group, public_key, private_key, NULL, NULL, bn_ctx) ||
73       !EC_POINT_point2cbb(out, group, public_key, POINT_CONVERSION_UNCOMPRESSED,
74                           bn_ctx)) {
75     goto err;
76   }
77 
78   ret = 1;
79 
80 err:
81   EC_GROUP_free(group);
82   EC_POINT_free(public_key);
83   BN_CTX_end(bn_ctx);
84   BN_CTX_free(bn_ctx);
85   return ret;
86 }
87 
ssl_ec_point_finish(SSL_ECDH_CTX * ctx,uint8_t ** out_secret,size_t * out_secret_len,uint8_t * out_alert,const uint8_t * peer_key,size_t peer_key_len)88 static int ssl_ec_point_finish(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
89                                size_t *out_secret_len, uint8_t *out_alert,
90                                const uint8_t *peer_key, size_t peer_key_len) {
91   BIGNUM *private_key = (BIGNUM *)ctx->data;
92   assert(private_key != NULL);
93   *out_alert = SSL_AD_INTERNAL_ERROR;
94 
95   /* Set up a shared |BN_CTX| for all operations. */
96   BN_CTX *bn_ctx = BN_CTX_new();
97   if (bn_ctx == NULL) {
98     return 0;
99   }
100   BN_CTX_start(bn_ctx);
101 
102   int ret = 0;
103   EC_GROUP *group = EC_GROUP_new_by_curve_name(ctx->method->nid);
104   EC_POINT *peer_point = NULL, *result = NULL;
105   uint8_t *secret = NULL;
106   if (group == NULL) {
107     goto err;
108   }
109 
110   /* Compute the x-coordinate of |peer_key| * |private_key|. */
111   peer_point = EC_POINT_new(group);
112   result = EC_POINT_new(group);
113   if (peer_point == NULL || result == NULL) {
114     goto err;
115   }
116   BIGNUM *x = BN_CTX_get(bn_ctx);
117   if (x == NULL) {
118     goto err;
119   }
120   if (!EC_POINT_oct2point(group, peer_point, peer_key, peer_key_len, bn_ctx)) {
121     *out_alert = SSL_AD_DECODE_ERROR;
122     goto err;
123   }
124   if (!EC_POINT_mul(group, result, NULL, peer_point, private_key, bn_ctx) ||
125       !EC_POINT_get_affine_coordinates_GFp(group, result, x, NULL, bn_ctx)) {
126     goto err;
127   }
128 
129   /* Encode the x-coordinate left-padded with zeros. */
130   size_t secret_len = (EC_GROUP_get_degree(group) + 7) / 8;
131   secret = OPENSSL_malloc(secret_len);
132   if (secret == NULL || !BN_bn2bin_padded(secret, secret_len, x)) {
133     goto err;
134   }
135 
136   *out_secret = secret;
137   *out_secret_len = secret_len;
138   secret = NULL;
139   ret = 1;
140 
141 err:
142   EC_GROUP_free(group);
143   EC_POINT_free(peer_point);
144   EC_POINT_free(result);
145   BN_CTX_end(bn_ctx);
146   BN_CTX_free(bn_ctx);
147   OPENSSL_free(secret);
148   return ret;
149 }
150 
ssl_ec_point_accept(SSL_ECDH_CTX * ctx,CBB * out_public_key,uint8_t ** out_secret,size_t * out_secret_len,uint8_t * out_alert,const uint8_t * peer_key,size_t peer_key_len)151 static int ssl_ec_point_accept(SSL_ECDH_CTX *ctx, CBB *out_public_key,
152                                uint8_t **out_secret, size_t *out_secret_len,
153                                uint8_t *out_alert, const uint8_t *peer_key,
154                                size_t peer_key_len) {
155   *out_alert = SSL_AD_INTERNAL_ERROR;
156   if (!ssl_ec_point_offer(ctx, out_public_key) ||
157       !ssl_ec_point_finish(ctx, out_secret, out_secret_len, out_alert, peer_key,
158                            peer_key_len)) {
159     return 0;
160   }
161   return 1;
162 }
163 
164 /* X25119 implementation. */
165 
ssl_x25519_cleanup(SSL_ECDH_CTX * ctx)166 static void ssl_x25519_cleanup(SSL_ECDH_CTX *ctx) {
167   if (ctx->data == NULL) {
168     return;
169   }
170   OPENSSL_cleanse(ctx->data, 32);
171   OPENSSL_free(ctx->data);
172 }
173 
ssl_x25519_offer(SSL_ECDH_CTX * ctx,CBB * out)174 static int ssl_x25519_offer(SSL_ECDH_CTX *ctx, CBB *out) {
175   assert(ctx->data == NULL);
176 
177   ctx->data = OPENSSL_malloc(32);
178   if (ctx->data == NULL) {
179     OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
180     return 0;
181   }
182   uint8_t public_key[32];
183   X25519_keypair(public_key, (uint8_t *)ctx->data);
184   return CBB_add_bytes(out, public_key, sizeof(public_key));
185 }
186 
ssl_x25519_finish(SSL_ECDH_CTX * ctx,uint8_t ** out_secret,size_t * out_secret_len,uint8_t * out_alert,const uint8_t * peer_key,size_t peer_key_len)187 static int ssl_x25519_finish(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
188                              size_t *out_secret_len, uint8_t *out_alert,
189                              const uint8_t *peer_key, size_t peer_key_len) {
190   assert(ctx->data != NULL);
191   *out_alert = SSL_AD_INTERNAL_ERROR;
192 
193   uint8_t *secret = OPENSSL_malloc(32);
194   if (secret == NULL) {
195     return 0;
196   }
197 
198   if (peer_key_len != 32 ||
199       !X25519(secret, (uint8_t *)ctx->data, peer_key)) {
200     OPENSSL_free(secret);
201     *out_alert = SSL_AD_DECODE_ERROR;
202     OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT);
203     return 0;
204   }
205 
206   *out_secret = secret;
207   *out_secret_len = 32;
208   return 1;
209 }
210 
ssl_x25519_accept(SSL_ECDH_CTX * ctx,CBB * out_public_key,uint8_t ** out_secret,size_t * out_secret_len,uint8_t * out_alert,const uint8_t * peer_key,size_t peer_key_len)211 static int ssl_x25519_accept(SSL_ECDH_CTX *ctx, CBB *out_public_key,
212                              uint8_t **out_secret, size_t *out_secret_len,
213                              uint8_t *out_alert, const uint8_t *peer_key,
214                              size_t peer_key_len) {
215   *out_alert = SSL_AD_INTERNAL_ERROR;
216   if (!ssl_x25519_offer(ctx, out_public_key) ||
217       !ssl_x25519_finish(ctx, out_secret, out_secret_len, out_alert, peer_key,
218                          peer_key_len)) {
219     return 0;
220   }
221   return 1;
222 }
223 
224 
225 /* Combined X25119 + New Hope (post-quantum) implementation. */
226 
227 typedef struct {
228   uint8_t x25519_key[32];
229   NEWHOPE_POLY *newhope_sk;
230 } cecpq1_data;
231 
232 #define CECPQ1_OFFERMSG_LENGTH (32 + NEWHOPE_OFFERMSG_LENGTH)
233 #define CECPQ1_ACCEPTMSG_LENGTH (32 + NEWHOPE_ACCEPTMSG_LENGTH)
234 #define CECPQ1_SECRET_LENGTH (32 + SHA256_DIGEST_LENGTH)
235 
ssl_cecpq1_cleanup(SSL_ECDH_CTX * ctx)236 static void ssl_cecpq1_cleanup(SSL_ECDH_CTX *ctx) {
237   if (ctx->data == NULL) {
238     return;
239   }
240   cecpq1_data *data = ctx->data;
241   NEWHOPE_POLY_free(data->newhope_sk);
242   OPENSSL_cleanse(data, sizeof(cecpq1_data));
243   OPENSSL_free(data);
244 }
245 
ssl_cecpq1_offer(SSL_ECDH_CTX * ctx,CBB * out)246 static int ssl_cecpq1_offer(SSL_ECDH_CTX *ctx, CBB *out) {
247   assert(ctx->data == NULL);
248   cecpq1_data *data = OPENSSL_malloc(sizeof(cecpq1_data));
249   if (data == NULL) {
250     OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
251     return 0;
252   }
253   ctx->data = data;
254   data->newhope_sk = NEWHOPE_POLY_new();
255   if (data->newhope_sk == NULL) {
256     OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
257     return 0;
258   }
259 
260   uint8_t x25519_public_key[32];
261   X25519_keypair(x25519_public_key, data->x25519_key);
262 
263   uint8_t newhope_offermsg[NEWHOPE_OFFERMSG_LENGTH];
264   NEWHOPE_offer(newhope_offermsg, data->newhope_sk);
265 
266   if (!CBB_add_bytes(out, x25519_public_key, sizeof(x25519_public_key)) ||
267       !CBB_add_bytes(out, newhope_offermsg, sizeof(newhope_offermsg))) {
268     return 0;
269   }
270   return 1;
271 }
272 
ssl_cecpq1_accept(SSL_ECDH_CTX * ctx,CBB * cbb,uint8_t ** out_secret,size_t * out_secret_len,uint8_t * out_alert,const uint8_t * peer_key,size_t peer_key_len)273 static int ssl_cecpq1_accept(SSL_ECDH_CTX *ctx, CBB *cbb, uint8_t **out_secret,
274                              size_t *out_secret_len, uint8_t *out_alert,
275                              const uint8_t *peer_key, size_t peer_key_len) {
276   if (peer_key_len != CECPQ1_OFFERMSG_LENGTH) {
277     *out_alert = SSL_AD_DECODE_ERROR;
278     return 0;
279   }
280 
281   *out_alert = SSL_AD_INTERNAL_ERROR;
282 
283   assert(ctx->data == NULL);
284   cecpq1_data *data = OPENSSL_malloc(sizeof(cecpq1_data));
285   if (data == NULL) {
286     OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
287     return 0;
288   }
289   data->newhope_sk = NULL;
290   ctx->data = data;
291 
292   uint8_t *secret = OPENSSL_malloc(CECPQ1_SECRET_LENGTH);
293   if (secret == NULL) {
294     OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
295     return 0;
296   }
297 
298   /* Generate message to server, and secret key, at once. */
299 
300   uint8_t x25519_public_key[32];
301   X25519_keypair(x25519_public_key, data->x25519_key);
302   if (!X25519(secret, data->x25519_key, peer_key)) {
303     *out_alert = SSL_AD_DECODE_ERROR;
304     OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT);
305     goto err;
306   }
307 
308   uint8_t newhope_acceptmsg[NEWHOPE_ACCEPTMSG_LENGTH];
309   if (!NEWHOPE_accept(secret + 32, newhope_acceptmsg, peer_key + 32,
310                       NEWHOPE_OFFERMSG_LENGTH)) {
311     *out_alert = SSL_AD_DECODE_ERROR;
312     goto err;
313   }
314 
315   if (!CBB_add_bytes(cbb, x25519_public_key, sizeof(x25519_public_key)) ||
316       !CBB_add_bytes(cbb, newhope_acceptmsg, sizeof(newhope_acceptmsg))) {
317     goto err;
318   }
319 
320   *out_secret = secret;
321   *out_secret_len = CECPQ1_SECRET_LENGTH;
322   return 1;
323 
324  err:
325   OPENSSL_cleanse(secret, CECPQ1_SECRET_LENGTH);
326   OPENSSL_free(secret);
327   return 0;
328 }
329 
ssl_cecpq1_finish(SSL_ECDH_CTX * ctx,uint8_t ** out_secret,size_t * out_secret_len,uint8_t * out_alert,const uint8_t * peer_key,size_t peer_key_len)330 static int ssl_cecpq1_finish(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
331                              size_t *out_secret_len, uint8_t *out_alert,
332                              const uint8_t *peer_key, size_t peer_key_len) {
333   if (peer_key_len != CECPQ1_ACCEPTMSG_LENGTH) {
334     *out_alert = SSL_AD_DECODE_ERROR;
335     return 0;
336   }
337 
338   *out_alert = SSL_AD_INTERNAL_ERROR;
339 
340   assert(ctx->data != NULL);
341   cecpq1_data *data = ctx->data;
342 
343   uint8_t *secret = OPENSSL_malloc(CECPQ1_SECRET_LENGTH);
344   if (secret == NULL) {
345     OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
346     return 0;
347   }
348 
349   if (!X25519(secret, data->x25519_key, peer_key)) {
350     *out_alert = SSL_AD_DECODE_ERROR;
351     OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT);
352     goto err;
353   }
354 
355   if (!NEWHOPE_finish(secret + 32, data->newhope_sk, peer_key + 32,
356                       NEWHOPE_ACCEPTMSG_LENGTH)) {
357     *out_alert = SSL_AD_DECODE_ERROR;
358     goto err;
359   }
360 
361   *out_secret = secret;
362   *out_secret_len = CECPQ1_SECRET_LENGTH;
363   return 1;
364 
365  err:
366   OPENSSL_cleanse(secret, CECPQ1_SECRET_LENGTH);
367   OPENSSL_free(secret);
368   return 0;
369 }
370 
371 
372 /* Legacy DHE-based implementation. */
373 
ssl_dhe_cleanup(SSL_ECDH_CTX * ctx)374 static void ssl_dhe_cleanup(SSL_ECDH_CTX *ctx) {
375   DH_free((DH *)ctx->data);
376 }
377 
ssl_dhe_offer(SSL_ECDH_CTX * ctx,CBB * out)378 static int ssl_dhe_offer(SSL_ECDH_CTX *ctx, CBB *out) {
379   DH *dh = (DH *)ctx->data;
380   /* The group must have been initialized already, but not the key. */
381   assert(dh != NULL);
382   assert(dh->priv_key == NULL);
383 
384   /* Due to a bug in yaSSL, the public key must be zero padded to the size of
385    * the prime. */
386   return DH_generate_key(dh) &&
387          BN_bn2cbb_padded(out, BN_num_bytes(dh->p), dh->pub_key);
388 }
389 
ssl_dhe_finish(SSL_ECDH_CTX * ctx,uint8_t ** out_secret,size_t * out_secret_len,uint8_t * out_alert,const uint8_t * peer_key,size_t peer_key_len)390 static int ssl_dhe_finish(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
391                           size_t *out_secret_len, uint8_t *out_alert,
392                           const uint8_t *peer_key, size_t peer_key_len) {
393   DH *dh = (DH *)ctx->data;
394   assert(dh != NULL);
395   assert(dh->priv_key != NULL);
396   *out_alert = SSL_AD_INTERNAL_ERROR;
397 
398   int secret_len = 0;
399   uint8_t *secret = NULL;
400   BIGNUM *peer_point = BN_bin2bn(peer_key, peer_key_len, NULL);
401   if (peer_point == NULL) {
402     goto err;
403   }
404 
405   secret = OPENSSL_malloc(DH_size(dh));
406   if (secret == NULL) {
407     goto err;
408   }
409   secret_len = DH_compute_key(secret, peer_point, dh);
410   if (secret_len <= 0) {
411     goto err;
412   }
413 
414   *out_secret = secret;
415   *out_secret_len = (size_t)secret_len;
416   BN_free(peer_point);
417   return 1;
418 
419 err:
420   if (secret_len > 0) {
421     OPENSSL_cleanse(secret, (size_t)secret_len);
422   }
423   OPENSSL_free(secret);
424   BN_free(peer_point);
425   return 0;
426 }
427 
ssl_dhe_accept(SSL_ECDH_CTX * ctx,CBB * out_public_key,uint8_t ** out_secret,size_t * out_secret_len,uint8_t * out_alert,const uint8_t * peer_key,size_t peer_key_len)428 static int ssl_dhe_accept(SSL_ECDH_CTX *ctx, CBB *out_public_key,
429                           uint8_t **out_secret, size_t *out_secret_len,
430                           uint8_t *out_alert, const uint8_t *peer_key,
431                           size_t peer_key_len) {
432   *out_alert = SSL_AD_INTERNAL_ERROR;
433   if (!ssl_dhe_offer(ctx, out_public_key) ||
434       !ssl_dhe_finish(ctx, out_secret, out_secret_len, out_alert, peer_key,
435                       peer_key_len)) {
436     return 0;
437   }
438   return 1;
439 }
440 
441 static const SSL_ECDH_METHOD kDHEMethod = {
442     NID_undef, 0, "",
443     ssl_dhe_cleanup,
444     ssl_dhe_offer,
445     ssl_dhe_accept,
446     ssl_dhe_finish,
447     CBS_get_u16_length_prefixed,
448     CBB_add_u16_length_prefixed,
449 };
450 
451 static const SSL_ECDH_METHOD kMethods[] = {
452     {
453         NID_X9_62_prime256v1,
454         SSL_GROUP_SECP256R1,
455         "P-256",
456         ssl_ec_point_cleanup,
457         ssl_ec_point_offer,
458         ssl_ec_point_accept,
459         ssl_ec_point_finish,
460         CBS_get_u8_length_prefixed,
461         CBB_add_u8_length_prefixed,
462     },
463     {
464         NID_secp384r1,
465         SSL_GROUP_SECP384R1,
466         "P-384",
467         ssl_ec_point_cleanup,
468         ssl_ec_point_offer,
469         ssl_ec_point_accept,
470         ssl_ec_point_finish,
471         CBS_get_u8_length_prefixed,
472         CBB_add_u8_length_prefixed,
473     },
474     {
475         NID_secp521r1,
476         SSL_GROUP_SECP521R1,
477         "P-521",
478         ssl_ec_point_cleanup,
479         ssl_ec_point_offer,
480         ssl_ec_point_accept,
481         ssl_ec_point_finish,
482         CBS_get_u8_length_prefixed,
483         CBB_add_u8_length_prefixed,
484     },
485     {
486         NID_X25519,
487         SSL_GROUP_X25519,
488         "X25519",
489         ssl_x25519_cleanup,
490         ssl_x25519_offer,
491         ssl_x25519_accept,
492         ssl_x25519_finish,
493         CBS_get_u8_length_prefixed,
494         CBB_add_u8_length_prefixed,
495     },
496     {
497         NID_cecpq1,
498         SSL_GROUP_CECPQ1,
499         "CECPQ1",
500         ssl_cecpq1_cleanup,
501         ssl_cecpq1_offer,
502         ssl_cecpq1_accept,
503         ssl_cecpq1_finish,
504         CBS_get_u16_length_prefixed,
505         CBB_add_u16_length_prefixed,
506     },
507 };
508 
method_from_group_id(uint16_t group_id)509 static const SSL_ECDH_METHOD *method_from_group_id(uint16_t group_id) {
510   size_t i;
511   for (i = 0; i < sizeof(kMethods) / sizeof(kMethods[0]); i++) {
512     if (kMethods[i].group_id == group_id) {
513       return &kMethods[i];
514     }
515   }
516   return NULL;
517 }
518 
method_from_nid(int nid)519 static const SSL_ECDH_METHOD *method_from_nid(int nid) {
520   size_t i;
521   for (i = 0; i < sizeof(kMethods) / sizeof(kMethods[0]); i++) {
522     if (kMethods[i].nid == nid) {
523       return &kMethods[i];
524     }
525   }
526   return NULL;
527 }
528 
SSL_get_curve_name(uint16_t group_id)529 const char* SSL_get_curve_name(uint16_t group_id) {
530   const SSL_ECDH_METHOD *method = method_from_group_id(group_id);
531   if (method == NULL) {
532     return NULL;
533   }
534   return method->name;
535 }
536 
ssl_nid_to_group_id(uint16_t * out_group_id,int nid)537 int ssl_nid_to_group_id(uint16_t *out_group_id, int nid) {
538   const SSL_ECDH_METHOD *method = method_from_nid(nid);
539   if (method == NULL) {
540     return 0;
541   }
542   *out_group_id = method->group_id;
543   return 1;
544 }
545 
SSL_ECDH_CTX_init(SSL_ECDH_CTX * ctx,uint16_t group_id)546 int SSL_ECDH_CTX_init(SSL_ECDH_CTX *ctx, uint16_t group_id) {
547   SSL_ECDH_CTX_cleanup(ctx);
548 
549   const SSL_ECDH_METHOD *method = method_from_group_id(group_id);
550   if (method == NULL) {
551     OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_ELLIPTIC_CURVE);
552     return 0;
553   }
554   ctx->method = method;
555   return 1;
556 }
557 
SSL_ECDH_CTX_init_for_dhe(SSL_ECDH_CTX * ctx,DH * params)558 void SSL_ECDH_CTX_init_for_dhe(SSL_ECDH_CTX *ctx, DH *params) {
559   SSL_ECDH_CTX_cleanup(ctx);
560 
561   ctx->method = &kDHEMethod;
562   ctx->data = params;
563 }
564 
SSL_ECDH_CTX_get_key(SSL_ECDH_CTX * ctx,CBS * cbs,CBS * out)565 int SSL_ECDH_CTX_get_key(SSL_ECDH_CTX *ctx, CBS *cbs, CBS *out) {
566   if (ctx->method == NULL) {
567     return 0;
568   }
569   return ctx->method->get_key(cbs, out);
570 }
571 
SSL_ECDH_CTX_add_key(SSL_ECDH_CTX * ctx,CBB * cbb,CBB * out_contents)572 int SSL_ECDH_CTX_add_key(SSL_ECDH_CTX *ctx, CBB *cbb, CBB *out_contents) {
573   if (ctx->method == NULL) {
574     return 0;
575   }
576   return ctx->method->add_key(cbb, out_contents);
577 }
578 
SSL_ECDH_CTX_cleanup(SSL_ECDH_CTX * ctx)579 void SSL_ECDH_CTX_cleanup(SSL_ECDH_CTX *ctx) {
580   if (ctx->method == NULL) {
581     return;
582   }
583   ctx->method->cleanup(ctx);
584   ctx->method = NULL;
585   ctx->data = NULL;
586 }
587 
SSL_ECDH_CTX_offer(SSL_ECDH_CTX * ctx,CBB * out_public_key)588 int SSL_ECDH_CTX_offer(SSL_ECDH_CTX *ctx, CBB *out_public_key) {
589   return ctx->method->offer(ctx, out_public_key);
590 }
591 
SSL_ECDH_CTX_accept(SSL_ECDH_CTX * ctx,CBB * out_public_key,uint8_t ** out_secret,size_t * out_secret_len,uint8_t * out_alert,const uint8_t * peer_key,size_t peer_key_len)592 int SSL_ECDH_CTX_accept(SSL_ECDH_CTX *ctx, CBB *out_public_key,
593                         uint8_t **out_secret, size_t *out_secret_len,
594                         uint8_t *out_alert, const uint8_t *peer_key,
595                         size_t peer_key_len) {
596   return ctx->method->accept(ctx, out_public_key, out_secret, out_secret_len,
597                              out_alert, peer_key, peer_key_len);
598 }
599 
SSL_ECDH_CTX_finish(SSL_ECDH_CTX * ctx,uint8_t ** out_secret,size_t * out_secret_len,uint8_t * out_alert,const uint8_t * peer_key,size_t peer_key_len)600 int SSL_ECDH_CTX_finish(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
601                         size_t *out_secret_len, uint8_t *out_alert,
602                         const uint8_t *peer_key, size_t peer_key_len) {
603   return ctx->method->finish(ctx, out_secret, out_secret_len, out_alert,
604                              peer_key, peer_key_len);
605 }
606