static int ssl_cecpq1_offer(SSL_ECDH_CTX *ctx, CBB *out) { assert(ctx->data == NULL); cecpq1_data *data = OPENSSL_malloc(sizeof(cecpq1_data)); if (data == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); return 0; } ctx->data = data; data->newhope_sk = NEWHOPE_POLY_new(); if (data->newhope_sk == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); return 0; } uint8_t x25519_public_key[32]; X25519_keypair(x25519_public_key, data->x25519_key); uint8_t newhope_offermsg[NEWHOPE_OFFERMSG_LENGTH]; NEWHOPE_offer(newhope_offermsg, data->newhope_sk); if (!CBB_add_bytes(out, x25519_public_key, sizeof(x25519_public_key)) || !CBB_add_bytes(out, newhope_offermsg, sizeof(newhope_offermsg))) { return 0; } return 1; }
static int 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) { if (peer_key_len != CECPQ1_OFFERMSG_LENGTH) { *out_alert = SSL_AD_DECODE_ERROR; return 0; } *out_alert = SSL_AD_INTERNAL_ERROR; assert(ctx->data == NULL); cecpq1_data *data = OPENSSL_malloc(sizeof(cecpq1_data)); if (data == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); return 0; } data->newhope_sk = NULL; ctx->data = data; uint8_t *secret = OPENSSL_malloc(CECPQ1_SECRET_LENGTH); if (secret == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); return 0; } /* Generate message to server, and secret key, at once. */ uint8_t x25519_public_key[32]; X25519_keypair(x25519_public_key, data->x25519_key); if (!X25519(secret, data->x25519_key, peer_key)) { *out_alert = SSL_AD_DECODE_ERROR; OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT); goto err; } uint8_t newhope_acceptmsg[NEWHOPE_ACCEPTMSG_LENGTH]; if (!NEWHOPE_accept(secret + 32, newhope_acceptmsg, peer_key + 32, NEWHOPE_OFFERMSG_LENGTH)) { *out_alert = SSL_AD_DECODE_ERROR; goto err; } if (!CBB_add_bytes(cbb, x25519_public_key, sizeof(x25519_public_key)) || !CBB_add_bytes(cbb, newhope_acceptmsg, sizeof(newhope_acceptmsg))) { goto err; } *out_secret = secret; *out_secret_len = CECPQ1_SECRET_LENGTH; return 1; err: OPENSSL_cleanse(secret, CECPQ1_SECRET_LENGTH); OPENSSL_free(secret); return 0; }
static int ssl_x25519_offer(SSL_ECDH_CTX *ctx, CBB *out) { assert(ctx->data == NULL); ctx->data = OPENSSL_malloc(32); if (ctx->data == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); return 0; } uint8_t public_key[32]; X25519_keypair(public_key, (uint8_t *)ctx->data); return CBB_add_bytes(out, public_key, sizeof(public_key)); }