Files
GmSSL/ssl/statem/statem_gmtls.c
Zhi Guan b54a3d35e6 Update SM9 schemes
Update SM9 schemes based on the default sm9bn256v1 r-ate pairing. To be continued.
2018-09-28 22:21:44 +08:00

2248 lines
57 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* ====================================================================
* Copyright (c) 2014 - 2018 The GmSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the GmSSL Project.
* (http://gmssl.org/)"
*
* 4. The name "GmSSL Project" must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact
* guanzhi1980@gmail.com.
*
* 5. Products derived from this software may not be called "GmSSL"
* nor may "GmSSL" appear in their names without prior written
* permission of the GmSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the GmSSL Project
* (http://gmssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*/
#include <stdio.h>
#include <openssl/opensslconf.h>
# include "../ssl_locl.h"
# include "statem_locl.h"
# include "internal/constant_time_locl.h"
# include <openssl/buffer.h>
# include <openssl/rand.h>
# include <openssl/objects.h>
# include <openssl/evp.h>
# include <openssl/hmac.h>
# include <openssl/x509.h>
# include <openssl/x509v3.h>
# include <openssl/bn.h>
# include <openssl/sm2.h>
# include <openssl/crypto.h>
static int gmtls_output_cert_chain(SSL *s, int *len, int a_idx, int k_idx)
{
unsigned char *p;
unsigned long l = *len;
BUF_MEM *buf = s->init_buf;
int i;
STACK_OF(X509) *extra_certs;
STACK_OF(X509) *chain = NULL;
X509_STORE *chain_store;
CERT_PKEY *a_cpk;
CERT_PKEY *k_cpk;
if (!BUF_MEM_grow_clean(buf, 10)) {
SSLerr(SSL_F_GMTLS_OUTPUT_CERT_CHAIN, ERR_R_BUF_LIB);
return 0;
}
a_cpk = &s->cert->pkeys[a_idx];
k_cpk = &s->cert->pkeys[k_idx];
if (a_cpk->chain)
extra_certs = a_cpk->chain;
else if (k_cpk->chain)
extra_certs = k_cpk->chain;
else
extra_certs = s->ctx->extra_certs;
if ((s->mode & SSL_MODE_NO_AUTO_CHAIN) || extra_certs)
chain_store = NULL;
else if (s->cert->chain_store)
chain_store = s->cert->chain_store;
else
chain_store = s->ctx->cert_store;
if (chain_store) {
X509_STORE_CTX *xs_ctx = X509_STORE_CTX_new();
if (xs_ctx == NULL) {
SSLerr(SSL_F_GMTLS_OUTPUT_CERT_CHAIN, ERR_R_MALLOC_FAILURE);
return (0);
}
if (!X509_STORE_CTX_init(xs_ctx, chain_store, a_cpk->x509, NULL)) {
X509_STORE_CTX_free(xs_ctx);
SSLerr(SSL_F_GMTLS_OUTPUT_CERT_CHAIN, ERR_R_X509_LIB);
return (0);
}
/*
* It is valid for the chain not to be complete (because normally we
* don't include the root cert in the chain). Therefore we deliberately
* ignore the error return from this call. We're not actually verifying
* the cert - we're just building as much of the chain as we can
*/
(void)X509_verify_cert(xs_ctx);
/* Don't leave errors in the queue */
ERR_clear_error();
chain = X509_STORE_CTX_get0_chain(xs_ctx);
i = ssl_security_cert_chain(s, chain, NULL, 0);
if (i != 1) {
X509_STORE_CTX_free(xs_ctx);
SSLerr(SSL_F_GMTLS_OUTPUT_CERT_CHAIN, i);
return 0;
}
#if 0
OPENSSL_assert(s->cert->pkeys[a_idx].x509 != NULL);
OPENSSL_assert(s->cert->pkeys[k_idx].x509 != NULL);
X509_print_fp(stderr, s->cert->pkeys[a_idx].x509);
X509_print_fp(stderr, s->cert->pkeys[k_idx].x509);
#endif
/* add signing certificate */
if (!ssl_add_cert_to_buf(buf, &l, s->cert->pkeys[a_idx].x509)) {
return 0;
}
/* add key exchange certificate */
if (!ssl_add_cert_to_buf(buf, &l, s->cert->pkeys[k_idx].x509)) {
return 0;
}
/* add the following chain */
for (i = 1; i < sk_X509_num(chain); i++) {
X509 *x = sk_X509_value(chain, i);
if (!ssl_add_cert_to_buf(buf, &l, x)) {
X509_STORE_CTX_free(xs_ctx);
return 0;
}
}
X509_STORE_CTX_free(xs_ctx);
} else {
i = ssl_security_cert_chain(s, extra_certs, a_cpk->x509, 0);
if (i != 1) {
SSLerr(SSL_F_GMTLS_OUTPUT_CERT_CHAIN, i);
return 0;
}
/* output sign cert and exch cert */
if (!ssl_add_cert_to_buf(buf, &l, s->cert->pkeys[a_idx].x509)) {
return 0;
}
if (!ssl_add_cert_to_buf(buf, &l, s->cert->pkeys[k_idx].x509)) {
return 0;
}
/* output the following chain */
for (i = 0; i < sk_X509_num(extra_certs); i++) {
X509 *x = sk_X509_value(extra_certs, i);
if (!ssl_add_cert_to_buf(buf, &l, x)) {
return 0;
}
}
}
l -= 3 + SSL_HM_HEADER_LENGTH(s);
p = ssl_handshake_start(s);
l2n3(l, p);
l += 3;
*len = (int)l;
return 1;
}
#define gmtls_construct_sm2_certs(s,l) \
gmtls_output_cert_chain(s,l,SSL_PKEY_SM2,SSL_PKEY_SM2_ENC)
#define gmtls_construct_rsa_certs(s,l) \
gmtls_output_cert_chain(s,l,SSL_PKEY_RSA_SIGN,SSL_PKEY_RSA_ENC)
static int gmtls_process_sm2_certs(SSL *s, PACKET *pkt, int *al)
{
return 0;
}
static int gmtls_process_rsa_certs(SSL *s, PACKET *pkt, int *al)
{
return 0;
}
static int gmtls_construct_sm9_params(SSL *s, unsigned char **p, int *l, int *al, int ibe)
{
CERT_SM9 *sm9;
unsigned char *d;
size_t idlen;
int n;
*al = SSL_AD_INTERNAL_ERROR;
sm9 = ibe ? &s->cert->ibe : &s->cert->ibs;
if (!sm9->id || !sm9->params) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SM9_PARAMS, ERR_R_INTERNAL_ERROR);
return 0;
}
idlen = strlen(sm9->id);
if (!idlen || idlen > SM9_MAX_ID_LENGTH) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SM9_PARAMS, ERR_R_INTERNAL_ERROR);
return 0;
}
d = *p;
s2n(idlen, d);
memcpy(d, sm9->id, idlen);
d += idlen;
*p = d + 3;
if ((n = i2d_SM9PublicParameters(sm9->params, p)) < 0) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SM9_PARAMS, ERR_R_SM9_LIB);
return 0;
}
l2n3(n, d);
*l = 2 + idlen + 3 + n;
*al = -1;
return 1;
}
static int gmtls_process_sm9_params(SSL *s, PACKET *pkt, int *al, int ibe)
{
CERT_SM9 *sm9;
PACKET id, params;
const unsigned char *p;
*al = SSL_AD_INTERNAL_ERROR;
sm9 = ibe ? &s->session->ibe : &s->session->ibs;
if (sm9->id || sm9->params || sm9->publickey) {
SSLerr(SSL_F_GMTLS_PROCESS_SM9_PARAMS, ERR_R_INTERNAL_ERROR);
return 0;
}
if (!PACKET_get_length_prefixed_2(pkt, &id)) {
*al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_GMTLS_PROCESS_SM9_PARAMS, SSL_R_LENGTH_MISMATCH);
return 0;
}
if (PACKET_remaining(&id) <= 0
|| PACKET_remaining(&id) > SM9_MAX_ID_LENGTH
|| !PACKET_data(&id)[PACKET_remaining(&id) - 1]) {
*al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_GMTLS_PROCESS_SM9_PARAMS, SSL_R_LENGTH_MISMATCH);
return 0;
}
if (!(sm9->id = OPENSSL_malloc(PACKET_remaining(&id) + 1))) {
SSLerr(SSL_F_GMTLS_PROCESS_SM9_PARAMS, ERR_R_MALLOC_FAILURE);
return 0;
}
memcpy(sm9->id, PACKET_data(&id), PACKET_remaining(&id));
sm9->id[PACKET_remaining(&id)] = 0;
if (!PACKET_get_length_prefixed_3(pkt, &params)) {
*al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_GMTLS_PROCESS_SM9_PARAMS, SSL_R_LENGTH_MISMATCH);
return 0;
}
p = PACKET_data(&params);
if (!(sm9->params = d2i_SM9PublicParameters(NULL, &p,
PACKET_remaining(&params)))) {
*al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_GMTLS_PROCESS_SM9_PARAMS, ERR_R_INTERNAL_ERROR);//这个错误似乎不对
return 0;
}
/* check there is no remaining data */
if (p != PACKET_data(&params) + PACKET_remaining(&params)) {
*al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_GMTLS_PROCESS_SM9_PARAMS, SSL_R_LENGTH_MISMATCH);
return 0;
}
*al = -1;
return 1;
}
#define gmtls_construct_ibe_params(s,p,l,al) gmtls_construct_sm9_params(s,p,l,al,1)
#define gmtls_construct_ibs_params(s,p,l,al) gmtls_construct_sm9_params(s,p,l,al,0)
#define gmtls_process_ibe_params(s,pkt,al) gmtls_process_sm9_params(s,pkt,al,1)
#define gmtls_process_ibs_params(s,pkt,al) gmtls_process_sm9_params(s,pkt,al,0)
int gmtls_construct_server_certificate(SSL *s)
{
unsigned long alg_a;
alg_a = s->s3->tmp.new_cipher->algorithm_auth;
int l;
unsigned char *p;
int al = -1;
l = 3 + SSL_HM_HEADER_LENGTH(s);
if (alg_a & SSL_aSM2) {
if (!gmtls_construct_sm2_certs(s, &l)) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SERVER_CERTIFICATE,
ERR_R_INTERNAL_ERROR);
goto err;
}
} else if (alg_a & SSL_aRSA) {
if (!gmtls_construct_rsa_certs(s, &l)) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SERVER_CERTIFICATE,
ERR_R_INTERNAL_ERROR);
goto err;
}
} else if (alg_a & SSL_aSM9) {
if (!gmtls_construct_ibs_params(s, &p, &l, &al)) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SERVER_CERTIFICATE,
ERR_R_INTERNAL_ERROR);
goto err;
}
} else {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SERVER_CERTIFICATE,
ERR_R_INTERNAL_ERROR);
goto err;
}
if (!ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE, l)) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SERVER_CERTIFICATE,
ERR_R_INTERNAL_ERROR);
return 0;
}
return 1;
err:
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
ossl_statem_set_error(s);
return 0;
}
static int gmtls_process_server_certs(SSL *s, PACKET *pkt, int *al)
{
int ret;
STACK_OF(X509) *sk;
if ((ret = tls_process_server_certificate(s, pkt)) !=
MSG_PROCESS_CONTINUE_READING) {
SSLerr(SSL_F_GMTLS_PROCESS_SERVER_CERTS,
ERR_R_INTERNAL_ERROR);
return ret;
}
if (!(sk = s->session->peer_chain)) {
SSLerr(SSL_F_GMTLS_PROCESS_SERVER_CERTS,
ERR_R_INTERNAL_ERROR);
goto err;
}
/* check double certs */
if (sk_X509_num(sk) < 2) {
SSLerr(SSL_F_GMTLS_PROCESS_SERVER_CERTS,
SSL_R_INVALID_CERT_CHAIN);
goto err;
}
if (!(X509_get_key_usage(sk_X509_value(sk, 0)) &
X509v3_KU_DIGITAL_SIGNATURE)) {
SSLerr(SSL_F_GMTLS_PROCESS_SERVER_CERTS,
SSL_R_INVALID_CERT_CHAIN);
goto err;
}
if (!(X509_get_key_usage(sk_X509_value(sk, 1)) &
(X509v3_KU_KEY_ENCIPHERMENT | X509v3_KU_KEY_AGREEMENT))) {
SSLerr(SSL_F_GMTLS_PROCESS_SERVER_CERTS,
SSL_R_INVALID_CERT_CHAIN);
goto err;
}
err:
return 0;
}
MSG_PROCESS_RETURN gmtls_process_server_certificate(SSL *s, PACKET *pkt)
{
int al = -1;
unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth;
if (alg_a & SSL_aSM2) {
if (!gmtls_process_sm2_certs(s, pkt, &al)) {
SSLerr(SSL_F_GMTLS_PROCESS_SERVER_CERTIFICATE,
ERR_R_INTERNAL_ERROR);
goto err;
}
} else if (alg_a & SSL_aRSA) {
if (!gmtls_process_rsa_certs(s, pkt, &al)) {
SSLerr(SSL_F_GMTLS_PROCESS_SERVER_CERTIFICATE,
ERR_R_INTERNAL_ERROR);
goto err;
}
} else if (alg_a & SSL_aSM9) {
if (!gmtls_process_ibs_params(s, pkt, &al)) {
SSLerr(SSL_F_GMTLS_PROCESS_SERVER_CERTIFICATE,
ERR_R_INTERNAL_ERROR);
goto err;
}
} else {
al = SSL_AD_INTERNAL_ERROR;
SSLerr(SSL_F_GMTLS_PROCESS_SERVER_CERTIFICATE, ERR_R_INTERNAL_ERROR);
goto err;
}
return MSG_PROCESS_CONTINUE_READING;
err:
ssl3_send_alert(s, SSL3_AL_FATAL, al);
ossl_statem_set_error(s);
return MSG_PROCESS_ERROR;
}
static int gmtls_construct_ske_sm2dhe(SSL *s, unsigned char **p, int *l, int *al)
{
int ret = 0;
X509 *x509;
EVP_PKEY *pkey;
unsigned char *d;
int curve_id;
unsigned char *encodedPoint = NULL;
int encodedlen;
EVP_MD_CTX *md_ctx = NULL;
unsigned char z[EVP_MAX_MD_SIZE];
size_t zlen;
char *id = NULL;
unsigned int siglen;
*al = SSL_AD_INTERNAL_ERROR;
/* get signing cert and pkey */
if (!(x509 = s->cert->pkeys[SSL_PKEY_SM2].x509)) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SKE_SM2DHE, ERR_R_EVP_LIB);
return 0;
}
if (!(pkey = s->cert->pkeys[SSL_PKEY_SM2].privatekey)) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SKE_SM2DHE, ERR_R_INTERNAL_ERROR);
return 0;
}
/* check tmp pkey not set */
if (s->s3->tmp.pkey) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SKE_SM2DHE, ERR_R_INTERNAL_ERROR);
return 0;
}
d = *p;
/* output ECParameters as NameCurve */
*d++ = NAMED_CURVE_TYPE;
*d++ = 0;
*d++ = 30;
/* generate tmp pkey and output ECPoint */
if (!(curve_id = tls1_ec_nid2curve_id(NID_sm2p256v1))) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SKE_SM2DHE, ERR_R_INTERNAL_ERROR);
return 0;
}
if (!(s->s3->tmp.pkey = ssl_generate_pkey_curve(curve_id))) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SKE_SM2DHE, ERR_R_INTERNAL_ERROR);
return 0;
}
if (!(encodedlen = EVP_PKEY_get1_tls_encodedpoint(s->s3->tmp.pkey,
&encodedPoint))) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SKE_SM2DHE, ERR_R_MALLOC_FAILURE);
goto end;
}
*d++ = encodedlen;
memcpy(d, encodedPoint, encodedlen);
d += encodedlen;
/* malloc sign ctx */
if (!(md_ctx = EVP_MD_CTX_new())) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SKE_SM2DHE, ERR_R_MALLOC_FAILURE);
goto end;
}
/* sign digest of {client_random, server_random, sm2dhe_params} */
if (EVP_SignInit_ex(md_ctx, EVP_sm3(), NULL) <= 0) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SKE_SM2DHE, ERR_R_EVP_LIB);
goto end;
}
if (!(id = X509_NAME_oneline(X509_get_subject_name(x509), NULL, 0))) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SKE_SM2DHE, ERR_R_EVP_LIB);
goto end;
}
zlen = sizeof(z);
if (!SM2_compute_id_digest(EVP_sm3(), id, strlen(id), z, &zlen,
EVP_PKEY_get0_EC_KEY(pkey))) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SKE_SM2DHE, ERR_R_SM2_LIB);
goto end;
}
if (EVP_SignUpdate(md_ctx, z, zlen) <= 0
|| EVP_SignUpdate(md_ctx, &(s->s3->client_random[0]),
SSL3_RANDOM_SIZE) <= 0
|| EVP_SignUpdate(md_ctx, &(s->s3->server_random[0]),
SSL3_RANDOM_SIZE) <= 0
|| EVP_SignUpdate(md_ctx, *p, 4 + encodedlen) <= 0) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SKE_SM2DHE, ERR_R_EVP_LIB);
goto end;
}
if (EVP_PKEY_size(pkey) < 0) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SKE_SM2DHE, ERR_R_INTERNAL_ERROR);
goto end;
}
siglen = (unsigned int)EVP_PKEY_size(pkey);
if (EVP_SignFinal(md_ctx, &(d[2]), &siglen, pkey) <= 0) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SKE_SM2DHE, ERR_R_EVP_LIB);
goto end;
}
s2n(siglen, d);
d += siglen;
*l += d - *p;
*p = d;
*al = -1;
ret = 1;
end:
if (!ret && s->s3->tmp.pkey) {
EVP_PKEY_free(s->s3->tmp.pkey);
s->s3->tmp.pkey = NULL;
}
OPENSSL_free(encodedPoint);
EVP_MD_CTX_free(md_ctx);
OPENSSL_free(id);
return ret;
}
static int gmtls_process_ske_sm2dhe(SSL *s, PACKET *pkt, int *al)
{
int ret = 0;
const unsigned char *ecparams;
PACKET encoded_pt;
EVP_PKEY_CTX *pctx = NULL;
int paramslen;
PACKET signature;
EVP_PKEY *pkey;
int maxsig;
char *id = NULL;
unsigned char z[EVP_MAX_MD_SIZE];
size_t zlen;
EVP_MD_CTX *md_ctx = NULL;
*al = SSL_AD_INTERNAL_ERROR;
/* parse ECParameter */
if (!PACKET_get_bytes(pkt, &ecparams, 3)) {
*al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_GMTLS_PROCESS_SKE_SM2DHE, SSL_R_LENGTH_TOO_SHORT);
return 0;
}
if (ecparams[0] != NAMED_CURVE_TYPE || ecparams[1] != 0 || ecparams[2] != 30) {
*al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_GMTLS_PROCESS_SKE_SM2DHE, SSL_R_WRONG_CURVE);
return 0;
}
/* parse ECPoint */
if (!PACKET_get_length_prefixed_1(pkt, &encoded_pt)) {
*al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_GMTLS_PROCESS_SKE_SM2DHE, SSL_R_LENGTH_MISMATCH);
return 0;
}
if (!(pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL))) {
SSLerr(SSL_F_GMTLS_PROCESS_SKE_SM2DHE, ERR_R_MALLOC_FAILURE);
return 0;
}
if (EVP_PKEY_paramgen_init(pctx) <= 0
|| EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, NID_sm2p256v1) <= 0
|| EVP_PKEY_paramgen(pctx, &s->s3->peer_tmp) <= 0) {
SSLerr(SSL_F_GMTLS_PROCESS_SKE_SM2DHE, ERR_R_EVP_LIB);
goto end;
}
if (s->s3->peer_tmp) {
SSLerr(SSL_F_GMTLS_PROCESS_SKE_SM2DHE, ERR_R_INTERNAL_ERROR);
goto end;
}
if (!EVP_PKEY_set1_tls_encodedpoint(s->s3->peer_tmp,
PACKET_data(&encoded_pt), PACKET_remaining(&encoded_pt))) {
*al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_GMTLS_PROCESS_SKE_SM2DHE, SSL_R_BAD_ECPOINT);
goto end;
}
// s->s3->peer_tmp 需要free吗出错的话
/* get ECDHEParams length */
paramslen = PACKET_data(pkt) - ecparams;
/* parse signature packet, check no data remaining */
if (!PACKET_get_length_prefixed_2(pkt, &signature)
|| PACKET_remaining(pkt) != 0) {
*al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_GMTLS_PROCESS_SKE_SM2DHE, SSL_R_LENGTH_MISMATCH);
goto end;
}
if (!(pkey = X509_get0_pubkey(s->session->peer))) {
SSLerr(SSL_F_GMTLS_PROCESS_SKE_SM2DHE, ERR_R_INTERNAL_ERROR);
goto end;
}
if ((maxsig = EVP_PKEY_size(pkey)) < 0) {
SSLerr(SSL_F_GMTLS_PROCESS_SKE_SM2DHE, ERR_R_INTERNAL_ERROR);
goto end;
}
if (PACKET_remaining(&signature) > (size_t)maxsig) {
*al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_GMTLS_PROCESS_SKE_SM2DHE, SSL_R_WRONG_SIGNATURE_LENGTH);
goto end;
}
/* prepare sm2 z value */
if (!(id = X509_NAME_oneline(
X509_get_subject_name(s->session->peer), NULL, 0))) {
SSLerr(SSL_F_GMTLS_PROCESS_SKE_SM2DHE, ERR_R_EVP_LIB);
goto end;
}
zlen = sizeof(z);
if (!SM2_compute_id_digest(EVP_sm3(), id, strlen(id), z, &zlen,
EVP_PKEY_get0_EC_KEY(pkey))) {
SSLerr(SSL_F_GMTLS_PROCESS_SKE_SM2DHE, ERR_R_SM2_LIB);
goto end;
}
/* verify the signature */
if (!(md_ctx = EVP_MD_CTX_new())) {
SSLerr(SSL_F_GMTLS_PROCESS_SKE_SM2DHE, ERR_R_MALLOC_FAILURE);
goto end;
}
if (EVP_VerifyInit_ex(md_ctx, EVP_sm3(), NULL) <= 0) {
SSLerr(SSL_F_GMTLS_PROCESS_SKE_SM2DHE, ERR_R_EVP_LIB);
goto end;
}
if (EVP_VerifyUpdate(md_ctx, z, zlen) <= 0
|| EVP_VerifyUpdate(md_ctx, &(s->s3->client_random[0]),
SSL3_RANDOM_SIZE) <= 0
|| EVP_VerifyUpdate(md_ctx, &(s->s3->server_random[0]),
SSL3_RANDOM_SIZE) <= 0
|| EVP_VerifyUpdate(md_ctx, ecparams, paramslen) <= 0) {
SSLerr(SSL_F_GMTLS_PROCESS_SKE_SM2DHE, ERR_R_EVP_LIB);
goto end;
}
if (EVP_VerifyFinal(md_ctx, PACKET_data(&signature),
PACKET_remaining(&signature), pkey) <= 0) {
*al = SSL_AD_DECRYPT_ERROR;
SSLerr(SSL_F_GMTLS_PROCESS_SKE_SM2DHE, SSL_R_BAD_SIGNATURE);
goto end;
}
*al = -1;
ret = 1;
end:
EVP_PKEY_CTX_free(pctx);
OPENSSL_free(id);
EVP_MD_CTX_free(md_ctx);
return ret;
}
static unsigned char *gmtls_new_cert_packet(X509 *x, int *l)
{
unsigned char *ret = NULL;
unsigned char *p;
int n;
if ((n = i2d_X509(x, NULL)) <= 0) {
SSLerr(SSL_F_GMTLS_NEW_CERT_PACKET, ERR_R_X509_LIB);
return NULL;
}
if (!(ret = OPENSSL_malloc(n + 3))) {
SSLerr(SSL_F_GMTLS_NEW_CERT_PACKET, ERR_R_X509_LIB);
return 0;
}
p = &(ret[3]);
if ((n = i2d_X509(x, &p)) <= 0) {
SSLerr(SSL_F_GMTLS_NEW_CERT_PACKET, ERR_R_X509_LIB);
goto end;
}
p = ret;
l2n3(n, p);
*l = n;
end:
return ret;
}
static int gmtls_construct_ske_sm2(SSL *s, unsigned char **p, int *l, int *al)
{
int ret = 0;
EVP_PKEY *pkey;
X509 *x509;
unsigned char *buf = NULL;
int n;
EVP_MD_CTX *md_ctx = NULL;
char *id = NULL;
unsigned char z[EVP_MAX_MD_SIZE];
size_t zlen;
unsigned char *d;
unsigned int siglen;
*al = SSL_AD_INTERNAL_ERROR;
/* prepare sign key */
if (!(pkey = s->cert->pkeys[SSL_PKEY_SM2].privatekey)) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SKE_SM2, ERR_R_INTERNAL_ERROR);
return 0;
}
/* prepare encrypt cert buffer */
if (!(x509 = s->cert->pkeys[SSL_PKEY_SM2_ENC].x509)) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SKE_SM2, ERR_R_INTERNAL_ERROR);
return 0;
}
if (!(buf = gmtls_new_cert_packet(x509, &n))) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SKE_SM2, ERR_R_INTERNAL_ERROR);
return 0;
}
/* mallco ctx */
if (!(md_ctx = EVP_MD_CTX_new())) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SKE_SM2, ERR_R_MALLOC_FAILURE);
goto end;
}
/* sign digest of {client_random, server_random, enc_cert} */
if (EVP_SignInit_ex(md_ctx, EVP_sm3(), NULL) <= 0) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SKE_SM2, ERR_R_EVP_LIB);
goto end;
}
if (!(id = X509_NAME_oneline(X509_get_subject_name(x509), NULL, 0))) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SKE_SM2, ERR_R_EVP_LIB);
goto end;
}
zlen = sizeof(z);
if (!SM2_compute_id_digest(EVP_sm3(), id, strlen(id), z, &zlen,
EVP_PKEY_get0_EC_KEY(pkey))) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SKE_SM2, ERR_R_SM2_LIB);
goto end;
}
#ifdef GMTLS_DEBUG
{
int i;
printf("Z=");
for (i = 0; i< zlen; i++)
printf("%02X",z[i]);
printf("\n");
printf("C=");
for (i = 0; i < n; i++)
printf("%02X",buf[i]);
printf("\n");
}
#endif
if (EVP_SignUpdate(md_ctx, z, zlen) <= 0
|| EVP_SignUpdate(md_ctx, &(s->s3->client_random[0]),
SSL3_RANDOM_SIZE) <= 0
|| EVP_SignUpdate(md_ctx, &(s->s3->server_random[0]),
SSL3_RANDOM_SIZE) <= 0
|| EVP_SignUpdate(md_ctx, buf, n) <= 0) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SKE_SM2, ERR_R_EVP_LIB);
goto end;
}
/* generate signature */
if (EVP_PKEY_size(pkey) < 0) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SKE_SM2, ERR_R_EVP_LIB);
goto end;
}
d = *p;
siglen = EVP_PKEY_size(pkey);
if (EVP_SignFinal(md_ctx, &(d[2]), &siglen, pkey) <= 0) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SKE_SM2, ERR_R_EVP_LIB);
goto end;
}
s2n(siglen, d);
*p += 2 + siglen;
*l += 2 + siglen;
*al = -1;
ret = 1;
end:
OPENSSL_free(buf);
EVP_MD_CTX_free(md_ctx);
OPENSSL_free(id);
return ret;
}
static int gmtls_process_ske_sm2(SSL *s, PACKET *pkt, int *al)
{
int ret = 0;
EVP_PKEY *pkey;
X509 *x509;
unsigned char *buf = NULL;
int n;
PACKET signature;
int maxsig;
EVP_MD_CTX *md_ctx = NULL;
char *id = NULL;
unsigned char z[EVP_MAX_MD_SIZE];
size_t zlen;
*al = SSL_AD_INTERNAL_ERROR;
/* get peer's signing pkey */
if (!(pkey = X509_get0_pubkey(s->session->peer))) {
SSLerr(SSL_F_GMTLS_PROCESS_SKE_SM2, ERR_R_INTERNAL_ERROR);
return 0;
}
/* get peer's encryption cert */
if (!(x509 = sk_X509_value(s->session->peer_chain, 1))) {
SSLerr(SSL_F_GMTLS_PROCESS_SKE_SM2, ERR_R_INTERNAL_ERROR);
return 0;
}
if (!(buf = gmtls_new_cert_packet(x509, &n))) {
SSLerr(SSL_F_GMTLS_PROCESS_SKE_SM2, ERR_R_INTERNAL_ERROR);
return 0;
}
/* get signature packet, check no data remaining */
if (!PACKET_get_length_prefixed_2(pkt, &signature)
|| PACKET_remaining(pkt) != 0) {
SSLerr(SSL_F_GMTLS_PROCESS_SKE_SM2, SSL_R_LENGTH_MISMATCH);
goto end;
}
maxsig = EVP_PKEY_size(pkey);
if (maxsig < 0) {
SSLerr(SSL_F_GMTLS_PROCESS_SKE_SM2, ERR_R_INTERNAL_ERROR);
goto end;
}
if (PACKET_remaining(&signature) > (size_t)maxsig) {
SSLerr(SSL_F_GMTLS_PROCESS_SKE_SM2, SSL_R_WRONG_SIGNATURE_LENGTH);
goto end;
}
/* verify the signature */
if (!(md_ctx = EVP_MD_CTX_new())) {
SSLerr(SSL_F_GMTLS_PROCESS_SKE_SM2, ERR_R_EVP_LIB);
goto end;
}
if (EVP_VerifyInit_ex(md_ctx, EVP_sm3(), NULL) <= 0) {
SSLerr(SSL_F_GMTLS_PROCESS_SKE_SM2, ERR_R_EVP_LIB);
goto end;
}
/* prepare sm2 z value */
if (!(id = X509_NAME_oneline(X509_get_subject_name(x509), NULL, 0))) {
SSLerr(SSL_F_GMTLS_PROCESS_SKE_SM2, ERR_R_EVP_LIB);
goto end;
}
zlen = sizeof(z);
if (!SM2_compute_id_digest(EVP_sm3(), id, strlen(id), z, &zlen,
EVP_PKEY_get0_EC_KEY(pkey))) {
SSLerr(SSL_F_GMTLS_PROCESS_SKE_SM2, ERR_R_SM2_LIB);
goto end;
}
{ int i; printf("Z="); for (i=0;i<zlen;i++) printf("%02X",z[i]); printf("\n"); }
{ int i; printf("C="); for (i=0;i<n;i++) printf("%02X",buf[i]); printf("\n"); }
if (EVP_VerifyUpdate(md_ctx, z, zlen) <= 0
|| EVP_VerifyUpdate(md_ctx, &(s->s3->client_random[0]),
SSL3_RANDOM_SIZE) <= 0
|| EVP_VerifyUpdate(md_ctx, &(s->s3->server_random[0]),
SSL3_RANDOM_SIZE) <= 0
|| EVP_VerifyUpdate(md_ctx, buf, n) <= 0) {
SSLerr(SSL_F_GMTLS_PROCESS_SKE_SM2, ERR_R_EVP_LIB);
goto end;
}
if (EVP_VerifyFinal(md_ctx, PACKET_data(&signature),
PACKET_remaining(&signature), pkey) <= 0) {
*al = SSL_AD_DECRYPT_ERROR;
SSLerr(SSL_F_GMTLS_PROCESS_SKE_SM2, SSL_R_BAD_SIGNATURE);
ERR_print_errors_fp(stderr);
goto end;
}
*al = -1;
ret = 1;
end:
OPENSSL_free(buf);
EVP_MD_CTX_free(md_ctx);
OPENSSL_free(id);
return ret;
}
static int gmtls_construct_ske_sm9(SSL *s, unsigned char **p, int *l, int *al, int dhe)
{
int ret = 0;
unsigned char *d;
EVP_MD_CTX *md_ctx = NULL;
unsigned char dgst[EVP_MAX_MD_SIZE];
unsigned int dgstlen;
size_t siglen;
*al = SSL_AD_INTERNAL_ERROR;
if (!s->cert->ibe.params || !s->cert->ibe.id
|| !s->cert->ibs.params || !s->cert->ibs.privatekey) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SKE_SM9, ERR_R_INTERNAL_ERROR);
return 0;
}
/* output IBE id and public parameters */
d = *p;
if (!gmtls_construct_ibe_params(s, p, l, al)) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SKE_SM9, ERR_R_INTERNAL_ERROR);
return 0;
}
if (!(md_ctx = EVP_MD_CTX_new())) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SKE_SM9, ERR_R_MALLOC_FAILURE);
return 0;
}
/* digest {ibe_params, randoms, ibe_enckey} */
if (EVP_DigestInit_ex(md_ctx, EVP_sm3(), NULL) <= 0) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SKE_SM9, ERR_R_EVP_LIB);
goto end;
}
if (EVP_DigestUpdate(md_ctx, &(s->s3->client_random[0]),
SSL3_RANDOM_SIZE) <= 0
|| EVP_DigestUpdate(md_ctx, &(s->s3->server_random[0]),
SSL3_RANDOM_SIZE) <= 0
|| EVP_DigestUpdate(md_ctx, d, *l) <= 0) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SKE_SM9, ERR_R_EVP_LIB);
goto end;
}
if (dhe) {
/* prepare IBE encryption key */
unsigned char ibc_enckey[1024];
if (!SM9PrivateKey_get_gmtls_public_key(s->cert->ibe.params,
s->cert->ibe.privatekey, ibc_enckey)) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SKE_SM9, ERR_R_INTERNAL_ERROR);
goto end;
}
if (EVP_DigestUpdate(md_ctx, ibc_enckey, sizeof(ibc_enckey)) <= 0) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SKE_SM9, ERR_R_EVP_LIB);
goto end;
}
}
dgstlen = sizeof(dgst);
if (EVP_DigestFinal_ex(md_ctx, dgst, &dgstlen) <= 0) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SKE_SM9, ERR_R_EVP_LIB);
goto end;
}
/* sign digest and output signature */
d = *p;
siglen = SM9_signature_size(s->cert->ibs.params);
#if 0
if (!SM9_sign(s->cert->ibs.params, dgst, dgstlen, &(d[2]), &siglen,
s->cert->ibs.privatekey)) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SKE_SM9, ERR_R_SM9_LIB);
goto end;
}
#endif
s2n(siglen, d);
*l += 2 + siglen;
*p += *l;
*al = -1;
ret = 1;
end:
EVP_MD_CTX_free(md_ctx);
return ret;
}
static int gmtls_process_ske_sm9(SSL *s, PACKET *pkt, int *al, int dhe)
{
int ret = 0;
const unsigned char *d;
int n;
PACKET signature;
int maxsig;
EVP_MD_CTX *md_ctx = NULL;
unsigned char dgst[EVP_MAX_MD_SIZE];
unsigned int dgstlen;
*al = SSL_AD_INTERNAL_ERROR;
/* parse ibe params */
d = PACKET_data(pkt);
n = PACKET_remaining(pkt);
if (!gmtls_process_ibe_params(s, pkt, al)) {
SSLerr(SSL_F_GMTLS_PROCESS_SKE_SM9, ERR_R_INTERNAL_ERROR);
return 0;
}
n -= PACKET_remaining(pkt);
/* parse ibs signature */
if (!PACKET_get_length_prefixed_2(pkt, &signature)
|| PACKET_remaining(pkt) != 0) {
*al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_GMTLS_PROCESS_SKE_SM9, SSL_R_LENGTH_MISMATCH);
return 0;
}
if ((maxsig = SM9_signature_size(s->session->ibs.params)) < 0) {
SSLerr(SSL_F_GMTLS_PROCESS_SKE_SM9, ERR_R_INTERNAL_ERROR);
return 0;
}
if (PACKET_remaining(&signature) > (size_t)maxsig) {
*al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_GMTLS_PROCESS_SKE_SM9, SSL_R_WRONG_SIGNATURE_LENGTH);
return 0;
}
/* verify the signature */
if (!(md_ctx = EVP_MD_CTX_new())) {
SSLerr(SSL_F_GMTLS_PROCESS_SKE_SM9, ERR_R_EVP_LIB);
return 0;
}
if (EVP_DigestInit_ex(md_ctx, EVP_sm3(), NULL) <= 0) {
SSLerr(SSL_F_GMTLS_PROCESS_SKE_SM9, ERR_R_EVP_LIB);
goto end;
}
if (EVP_VerifyUpdate(md_ctx, &(s->s3->client_random[0]),
SSL3_RANDOM_SIZE) <= 0
|| EVP_VerifyUpdate(md_ctx, &(s->s3->server_random[0]),
SSL3_RANDOM_SIZE) <= 0
|| EVP_VerifyUpdate(md_ctx, d, n) <= 0) {
SSLerr(SSL_F_GMTLS_PROCESS_SKE_SM9, ERR_R_EVP_LIB);
goto end;
}
if (!dhe) {
SM9PublicKey *pk = NULL;
unsigned char enckey[1024];
if (!(pk = SM9_extract_public_key(s->session->ibe.params,
s->session->ibe.id, strlen(s->session->ibe.id)))) {
SSLerr(SSL_F_GMTLS_PROCESS_SKE_SM9, ERR_R_INTERNAL_ERROR);
goto end;
}
if (!SM9PublicKey_get_gmtls_encoded(s->session->ibe.params,
s->session->ibe.publickey, enckey)) {
SM9PublicKey_free(pk);
SSLerr(SSL_F_GMTLS_PROCESS_SKE_SM9, ERR_R_INTERNAL_ERROR);
goto end;
}
if (EVP_DigestUpdate(md_ctx, enckey, sizeof(enckey)) <= 0) {
SM9PublicKey_free(pk);
SSLerr(SSL_F_GMTLS_PROCESS_SKE_SM9, ERR_R_EVP_LIB);
goto end;
}
SM9PublicKey_free(pk);
}
if (EVP_DigestFinal_ex(md_ctx, dgst, &dgstlen) <= 0) {
*al = SSL_AD_INTERNAL_ERROR;
SSLerr(SSL_F_GMTLS_PROCESS_SKE_SM9, ERR_R_EVP_LIB);
goto end;
}
/* verify signature */
#if 0
if (1 != SM9_verify(s->session->ibs.params, dgst, dgstlen,
PACKET_data(&signature), PACKET_remaining(&signature),
s->session->ibs.id, strlen(s->session->ibs.id))) {
*al = SSL_AD_DECRYPT_ERROR;
SSLerr(SSL_F_GMTLS_PROCESS_SKE_SM9, SSL_R_BAD_SIGNATURE);
goto end;
}
#endif
ret = 1;
end:
EVP_MD_CTX_free(md_ctx);
return ret;
}
static int gmtls_construct_ske_rsa(SSL *s, unsigned char **p, int *l, int *al)
{
int ret = 0;
EVP_PKEY *pkey;
X509 *x509;
const EVP_MD *md;
EVP_MD_CTX *md_ctx = NULL;
unsigned char *buf = NULL;
unsigned char *d;
int n;
unsigned int siglen;
*al = SSL_AD_INTERNAL_ERROR;
/* get digest algor */
if (!ssl_cipher_get_evp(s->session, NULL, &md, NULL, NULL, NULL, 0)) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SKE_RSA, ERR_R_INTERNAL_ERROR);
return 0;
}
/* get sign pkey */
if (!(pkey = s->cert->pkeys[SSL_PKEY_RSA_SIGN].privatekey)) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SKE_RSA, ERR_R_INTERNAL_ERROR);
goto end;
}
/* create encryption cert packet */
if (!(x509 = s->cert->pkeys[SSL_PKEY_SM2_ENC].x509)) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SKE_RSA, ERR_R_INTERNAL_ERROR);
return 0;
}
if (!(buf = gmtls_new_cert_packet(x509, &n))) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SKE_RSA, ERR_R_INTERNAL_ERROR);
return 0;
}
/* generate signature */
if (!(md_ctx = EVP_MD_CTX_new())) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SKE_RSA, ERR_R_MALLOC_FAILURE);
goto end;
}
if (EVP_SignInit_ex(md_ctx, md, NULL) <= 0) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SKE_RSA, ERR_R_EVP_LIB);
goto end;
}
if (EVP_SignUpdate(md_ctx, &(s->s3->client_random[0]),
SSL3_RANDOM_SIZE) <= 0
|| EVP_SignUpdate(md_ctx, &(s->s3->server_random[0]),
SSL3_RANDOM_SIZE) <= 0
|| EVP_SignUpdate(md_ctx, buf, n) <= 0) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SKE_RSA, ERR_R_EVP_LIB);
goto end;
}
siglen = EVP_PKEY_size(pkey);
d = *p;
if (EVP_SignFinal(md_ctx, &(d[2]), &siglen, pkey) <= 0) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_SKE_RSA, ERR_R_EVP_LIB);
goto end;
}
s2n(siglen, d);
*l = 2 + siglen;
*p += *l;
*al = -1;
ret = 1;
end:
EVP_MD_CTX_free(md_ctx);
OPENSSL_free(buf);
return ret;
}
static int gmtls_process_ske_rsa(SSL *s, PACKET *pkt, int *al)
{
int ret = 0;
EVP_PKEY *pkey;
X509 *x509;
PACKET signature;
int maxsig;
unsigned char *buf = NULL;
int n;
const EVP_MD *md;
EVP_MD_CTX *md_ctx = NULL;
*al = SSL_AD_INTERNAL_ERROR;
/* get peer's signing pkey */
if (!(pkey = X509_get0_pubkey(s->session->peer))) {
SSLerr(SSL_F_GMTLS_PROCESS_SKE_RSA, ERR_R_INTERNAL_ERROR);
return 0;
}
/* get peer's encryption cert */
if (!(x509 = sk_X509_value(s->session->peer_chain, 1))) {
SSLerr(SSL_F_GMTLS_PROCESS_SKE_RSA, ERR_R_INTERNAL_ERROR);
return 0;
}
/* get signature packet, check no data remaining */
if (!PACKET_get_length_prefixed_2(pkt, &signature) ||
PACKET_remaining(pkt) != 0) {
*al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_GMTLS_PROCESS_SKE_RSA, SSL_R_LENGTH_MISMATCH);
return 0;
}
maxsig = EVP_PKEY_size(pkey);
if (maxsig < 0) {
SSLerr(SSL_F_GMTLS_PROCESS_SKE_RSA, ERR_R_INTERNAL_ERROR);
return 0;
}
if (PACKET_remaining(&signature) > (size_t)maxsig) {
*al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_GMTLS_PROCESS_SKE_RSA, SSL_R_WRONG_SIGNATURE_LENGTH);
return 0;
}
/* encode cert to opaque<1..2^24-1> */
if (!(buf = gmtls_new_cert_packet(x509, &n))) {
SSLerr(SSL_F_GMTLS_PROCESS_SKE_RSA, ERR_R_INTERNAL_ERROR);
return 0;
}
/* verify the signature */
if (!(md_ctx = EVP_MD_CTX_new())) {
SSLerr(SSL_F_GMTLS_PROCESS_SKE_RSA, ERR_R_EVP_LIB);
goto end;
}
if (EVP_VerifyInit_ex(md_ctx, md, NULL) <= 0) {
SSLerr(SSL_F_GMTLS_PROCESS_SKE_RSA, ERR_R_EVP_LIB);
goto end;
}
if (EVP_VerifyUpdate(md_ctx, &(s->s3->client_random[0]),
SSL3_RANDOM_SIZE) <= 0
|| EVP_VerifyUpdate(md_ctx, &(s->s3->server_random[0]),
SSL3_RANDOM_SIZE) <= 0
|| EVP_VerifyUpdate(md_ctx, buf, n) <= 0) {
EVP_MD_CTX_free(md_ctx);
SSLerr(SSL_F_GMTLS_PROCESS_SKE_RSA, ERR_R_EVP_LIB);
goto end;
}
if (EVP_VerifyFinal(md_ctx, PACKET_data(&signature),
PACKET_remaining(&signature), pkey) <= 0) {
*al = SSL_AD_DECRYPT_ERROR;
SSLerr(SSL_F_GMTLS_PROCESS_SKE_RSA, SSL_R_BAD_SIGNATURE);
goto end;
}
*al = -1;
ret = 1;
end:
OPENSSL_free(buf);
EVP_MD_CTX_free(md_ctx);
return ret;
}
int gmtls_construct_server_key_exchange(SSL *s)
{
int al = -1;
unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
unsigned char *p = ssl_handshake_start(s);
int l = 0;
if (alg_k & SSL_kSM2) {
if (!gmtls_construct_ske_sm2(s, &p, &l, &al)) {
goto err;
}
} else if (alg_k & SSL_kSM2DHE) {
if (!gmtls_construct_ske_sm2dhe(s, &p, &l, &al)) {
goto err;
}
} else if (alg_k & SSL_kSM9) {
if (!gmtls_construct_ske_sm9(s, &p, &l, &al, 0)) {
goto err;
}
} else if (alg_k & SSL_kSM9DHE) {
if (!gmtls_construct_ske_sm9(s, &p, &l, &al, 1)) {
goto err;
}
} else if (alg_k & SSL_kRSA) {
if (!gmtls_construct_ske_rsa(s, &p, &l, &al)) {
goto err;
}
} else {
al = SSL_AD_HANDSHAKE_FAILURE;
SSLerr(SSL_F_GMTLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
ERR_R_INTERNAL_ERROR);
goto err;
}
if (!ssl_set_handshake_header(s, SSL3_MT_SERVER_KEY_EXCHANGE, l)) {
al = SSL_AD_HANDSHAKE_FAILURE;
SSLerr(SSL_F_GMTLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
ERR_R_INTERNAL_ERROR);
goto err;
}
return 1;
err:
ssl3_send_alert(s, SSL3_AL_FATAL, al);
ossl_statem_set_error(s);
return 0;
}
MSG_PROCESS_RETURN gmtls_process_server_key_exchange(SSL *s, PACKET *pkt)
{
int al = -1;
unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
if (alg_k & SSL_kSM2DHE) {
if (!gmtls_process_ske_sm2dhe(s, pkt, &al)) {
goto err;
}
} else if (alg_k & SSL_kSM2) {
if (!gmtls_process_ske_sm2(s, pkt, &al)) {
goto err;
}
} else if (alg_k & SSL_kSM9DHE) {
if (!gmtls_process_ske_sm9(s, pkt, &al, 1)) {
goto err;
}
} else if (alg_k & SSL_kSM9) {
if (!gmtls_process_ske_sm9(s, pkt, &al, 0)) {
goto err;
}
} else if (alg_k & SSL_kRSA) {
if (!gmtls_process_ske_rsa(s, pkt, &al)) {
goto err;
}
} else {
}
return MSG_PROCESS_CONTINUE_READING;
err:
if (al != -1)
ssl3_send_alert(s, SSL3_AL_FATAL, al);
ossl_statem_set_error(s);
return MSG_PROCESS_ERROR;
}
int gmtls_construct_client_certificate(SSL *s)
{
int al = -1;
unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth;
unsigned char *p;
int l;
if (alg_a & SSL_aSM2) {
if (!gmtls_construct_sm2_certs(s, &l)) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_CLIENT_CERTIFICATE,
ERR_R_INTERNAL_ERROR);
goto err;
}
} else if (alg_a & SSL_aRSA) {
if (!gmtls_construct_rsa_certs(s, &l)) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_CLIENT_CERTIFICATE,
ERR_R_INTERNAL_ERROR);
goto err;
}
} else if (alg_a & SSL_aSM9) {
if (!gmtls_construct_ibs_params(s, &p, &l, &al)) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_CLIENT_CERTIFICATE,
ERR_R_INTERNAL_ERROR);
goto err;
}
} else {
SSLerr(SSL_F_GMTLS_CONSTRUCT_CLIENT_CERTIFICATE,
ERR_R_INTERNAL_ERROR);
goto err;
}
if (!ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE, l)) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_CLIENT_CERTIFICATE,
ERR_R_INTERNAL_ERROR);
return 0;
}
return 1;
err:
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
ossl_statem_set_error(s);
return 0;
}
MSG_PROCESS_RETURN gmtls_process_client_certificate(SSL *s, PACKET *pkt)
{
int ret = MSG_PROCESS_ERROR;
ret = tls_process_client_certificate(s, pkt);
return ret;
}
// SM2密钥交换实际上不仅仅
// 实际上还需要知道我是客户端还是服务器
static int gmtls_sm2_derive(SSL *s, EVP_PKEY *privkey, EVP_PKEY *pubkey, int initiator)
{
int ret = 0;
EC_KEY *peer_ephem;
EC_KEY *ephem;
X509 *x509;
EVP_PKEY *pkey;
EC_KEY *sk;
X509 *peer_x509;
EVP_PKEY *peer_pkey;
EC_KEY *peer_pk;
char *id = NULL;
unsigned char z[EVP_MAX_MD_SIZE];
size_t zlen;
char *peer_id = NULL;
unsigned char peer_z[EVP_MAX_MD_SIZE];
size_t peer_zlen;
unsigned char *pms = NULL;
size_t pmslen;
if (!(peer_ephem = EVP_PKEY_get0_EC_KEY(pubkey))) {
SSLerr(SSL_F_GMTLS_SM2_DERIVE, ERR_R_INTERNAL_ERROR);
return 0;
}
if (!(ephem = EVP_PKEY_get0_EC_KEY(privkey))) {
SSLerr(SSL_F_GMTLS_SM2_DERIVE, ERR_R_INTERNAL_ERROR);
return 0;
}
/* prepare long-term keys */
if (!(x509 = s->cert->pkeys[SSL_PKEY_SM2_ENC].x509)) {
SSLerr(SSL_F_GMTLS_SM2_DERIVE, ERR_R_INTERNAL_ERROR);
return 0;
}
if (!(pkey = s->cert->pkeys[SSL_PKEY_SM2_ENC].privatekey)) {
SSLerr(SSL_F_GMTLS_SM2_DERIVE, ERR_R_INTERNAL_ERROR);
return 0;
}
if (!(sk = EVP_PKEY_get0_EC_KEY(pkey))) {
SSLerr(SSL_F_GMTLS_SM2_DERIVE, ERR_R_INTERNAL_ERROR);
return 0;
}
if (!(peer_x509 = sk_X509_value(s->session->peer_chain, 1))) {
SSLerr(SSL_F_GMTLS_SM2_DERIVE, ERR_R_INTERNAL_ERROR);
return 0;
}
peer_pkey = X509_get0_pubkey(x509);
if (!(peer_pk = EVP_PKEY_get0_EC_KEY(pkey))) {
SSLerr(SSL_F_GMTLS_SM2_DERIVE, ERR_R_INTERNAL_ERROR);
return 0;
}
/* generate z values */
if (!(id = X509_NAME_oneline(X509_get_subject_name(x509), NULL, 0))) {
SSLerr(SSL_F_GMTLS_SM2_DERIVE, ERR_R_INTERNAL_ERROR);
return 0;
}
if (!SM2_compute_id_digest(EVP_sm3(), id, strlen(id), z, &zlen, sk)) {
SSLerr(SSL_F_GMTLS_SM2_DERIVE, ERR_R_INTERNAL_ERROR);
goto end;
}
if (!(peer_id = X509_NAME_oneline(X509_get_subject_name(x509), NULL, 0))) {
SSLerr(SSL_F_GMTLS_SM2_DERIVE, ERR_R_INTERNAL_ERROR);
goto end;
}
if (!SM2_compute_id_digest(EVP_sm3(), peer_id, strlen(peer_id),
peer_z, &peer_zlen, peer_pk)) {
SSLerr(SSL_F_GMTLS_SM2_DERIVE, ERR_R_INTERNAL_ERROR);
goto end;
}
// 如何设定pmslen ??
pmslen = 48;
/* sm2 key exchange */
if (!SM2_compute_share_key(pms, &pmslen,
EC_KEY_get0_public_key(peer_ephem), ephem,
EC_KEY_get0_public_key(peer_pk), peer_z, sizeof(peer_z),
z, sizeof(z), sk, initiator)) {
SSLerr(SSL_F_GMTLS_SM2_DERIVE, ERR_R_INTERNAL_ERROR);
goto end;
}
if (s->server) {
ret = ssl_generate_master_secret(s, pms, pmslen, 1);
pms = NULL;
} else {
s->s3->tmp.pms = pms;
s->s3->tmp.pmslen = pmslen;
pms = NULL;
ret = 1;
}
end:
OPENSSL_free(id);
OPENSSL_free(peer_id);
return ret;
}
static int gmtls_construct_cke_sm2dhe(SSL *s, unsigned char **p, int *l, int *al)
{
int ret = 0;
EVP_PKEY *skey;
unsigned char *d;
EVP_PKEY *ckey = NULL;
unsigned char *encodedPoint = NULL;
int encodedlen;
*al = SSL_AD_INTERNAL_ERROR;
if (!(skey = s->s3->peer_tmp)) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_CKE_SM2DHE, ERR_R_INTERNAL_ERROR);
return 0;
}
d = *p;
*d++ = NAMED_CURVE_TYPE;
*d++ = 0;
*d++ = 30;
if (!(ckey = ssl_generate_pkey(skey))) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_CKE_SM2DHE, ERR_R_INTERNAL_ERROR);
return 0;
}
if (!gmtls_sm2_derive(s, ckey, skey, 0)) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_CKE_SM2DHE, ERR_R_INTERNAL_ERROR);
goto end;
}
if (!(encodedlen = EVP_PKEY_get1_tls_encodedpoint(ckey, &encodedPoint))) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_CKE_SM2DHE, ERR_R_EVP_LIB);
goto end;
}
*d++ = encodedlen;
memcpy(d, encodedPoint, encodedlen);
d += encodedlen;
*l = 4 + encodedlen;
*p = d;
*al = -1;
ret = 1;
end:
EVP_PKEY_free(ckey);
OPENSSL_free(encodedPoint);
return ret;
}
static int gmtls_process_cke_sm2dhe(SSL *s, PACKET *pkt, int *al)
{
int ret = 0;
const unsigned char *ecparams;
PACKET encoded_pt;
EVP_PKEY *skey = s->s3->tmp.pkey;
EVP_PKEY *ckey = NULL;
*al = SSL_AD_INTERNAL_ERROR;
if (!(skey = s->s3->tmp.pkey)) {
SSLerr(SSL_F_GMTLS_PROCESS_CKE_SM2DHE, ERR_R_INTERNAL_ERROR);
return 0;
}
if (!PACKET_get_bytes(pkt, &ecparams, 3)) {
*al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_GMTLS_PROCESS_CKE_SM2DHE, SSL_R_LENGTH_TOO_SHORT);
return 0;
}
if (ecparams[0] != NAMED_CURVE_TYPE || ecparams[1] != 0 || ecparams[2] != 30) {
*al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_GMTLS_PROCESS_CKE_SM2DHE, SSL_R_WRONG_CURVE);
return 0;
}
/* parse ECPoint */
if (!PACKET_get_length_prefixed_1(pkt, &encoded_pt)
|| PACKET_remaining(pkt) != 0) {
*al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_GMTLS_PROCESS_CKE_SM2DHE, SSL_R_LENGTH_MISMATCH);
return 0;
}
if (!(ckey = EVP_PKEY_new())) {
SSLerr(SSL_F_GMTLS_PROCESS_CKE_SM2DHE, ERR_R_MALLOC_FAILURE);
return 0;
}
if (EVP_PKEY_copy_parameters(ckey, skey) <= 0) {
SSLerr(SSL_F_GMTLS_PROCESS_CKE_SM2DHE, ERR_R_EVP_LIB);
goto end;
}
if (!EVP_PKEY_set1_tls_encodedpoint(ckey, PACKET_data(&encoded_pt),
PACKET_remaining(&encoded_pt))) {
*al = SSL_AD_HANDSHAKE_FAILURE;
SSLerr(SSL_F_GMTLS_PROCESS_CKE_SM2DHE, ERR_R_EVP_LIB);
goto end;
}
if (!gmtls_sm2_derive(s, skey, ckey, 1)) {
SSLerr(SSL_F_GMTLS_PROCESS_CKE_SM2DHE, ERR_R_INTERNAL_ERROR);
goto end;
}
*al = -1;
ret = 1;
end:
EVP_PKEY_free(s->s3->tmp.pkey);
s->s3->tmp.pkey = NULL;
EVP_PKEY_free(ckey);
return ret;
}
static int gmtls_construct_cke_sm2(SSL *s, unsigned char **p, int *l, int *al)
{
int ret = 0;
unsigned char *d;
EVP_PKEY *pkey = NULL;
EVP_PKEY_CTX *pctx = NULL;
size_t enclen;
unsigned char *pms = NULL;
size_t pmslen = 0;
X509 *x509;
*al = SSL_AD_INTERNAL_ERROR;
/* get sm2 encryption key from enc cert */
if (!(s->session->peer_chain)) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_CKE_SM2, ERR_R_INTERNAL_ERROR);
return 0;
}
if (!(x509 = sk_X509_value(s->session->peer_chain, 1))) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_CKE_SM2, ERR_R_INTERNAL_ERROR);
return 0;
}
pkey = X509_get0_pubkey(x509);
if (!EVP_PKEY_get0_EC_KEY(pkey)) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_CKE_SM2, ERR_R_INTERNAL_ERROR);
return 0;
}
/* generate pre_master_secret */
pmslen = SSL_MAX_MASTER_KEY_LENGTH;
if (!(pms = OPENSSL_malloc(pmslen))) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_CKE_SM2, ERR_R_MALLOC_FAILURE);
return 0;
}
pms[0] = s->client_version >> 8;
pms[1] = s->client_version & 0xff;
if (RAND_bytes(pms + 2, pmslen - 2) <= 0) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_CKE_SM2, ERR_R_INTERNAL_ERROR);
goto end;
}
/* encrypt pre_master_secret */
if (!(pctx = EVP_PKEY_CTX_new(pkey, NULL))) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_CKE_SM2, ERR_R_MALLOC_FAILURE);
goto end;
}
if (EVP_PKEY_encrypt_init(pctx) <= 0
|| !EVP_PKEY_CTX_set_ec_scheme(pctx, NID_sm_scheme)
|| !EVP_PKEY_CTX_set_ec_encrypt_param(pctx, NID_sm3)) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_CKE_SM2, ERR_R_EVP_LIB);
goto end;
}
if (EVP_PKEY_encrypt(pctx, NULL, &enclen, pms, pmslen) <= 0) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_CKE_SM2, ERR_R_EVP_LIB);
goto end;
}
d = *p;
if (EVP_PKEY_encrypt(pctx, &(d[2]), &enclen, pms, pmslen) <= 0) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_CKE_SM2, SSL_R_BAD_SM2_ENCRYPT);
goto end;
}
s2n(enclen, d);
d += enclen;
/* save pre_master_secret */
if (s->s3->tmp.pms) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_CKE_SM2, ERR_R_INTERNAL_ERROR);
goto end;
}
s->s3->tmp.pms = pms;
s->s3->tmp.pmslen = pmslen;
pms = NULL;
*p = d;
*l = 2 + enclen;
*al = -1;
ret = 1;
end:
OPENSSL_clear_free(pms, pmslen);
EVP_PKEY_CTX_free(pctx);
return ret;
}
static int gmtls_process_cke_sm2(SSL *s, PACKET *pkt, int *al)
{
int ret = 0;
EVP_PKEY *pkey;
PACKET enced_pms;
unsigned char rand_pms[SSL_MAX_MASTER_KEY_LENGTH];
EVP_PKEY_CTX *pctx = NULL;
size_t pmslen;
unsigned char pms[SSL_MAX_MASTER_KEY_LENGTH];
int ver_good;
int i;
*al = SSL_AD_INTERNAL_ERROR;
/* prepare decryption key */
if (!(pkey = s->cert->pkeys[SSL_PKEY_SM2_ENC].privatekey)) {
SSLerr(SSL_F_GMTLS_PROCESS_CKE_SM2, SSL_R_MISSING_SM2_ENC_CERTIFICATE);
return 0;
}
/* parse encrypted pre_master_secret */
if (!PACKET_get_length_prefixed_2(pkt, &enced_pms)
|| PACKET_remaining(pkt) != 0) {
*al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_GMTLS_PROCESS_CKE_SM2, SSL_R_LENGTH_MISMATCH);
return 0;
}
if (RAND_bytes(rand_pms, sizeof(rand_pms)) <= 0) {
SSLerr(SSL_F_GMTLS_PROCESS_CKE_SM2, ERR_R_INTERNAL_ERROR);
return 0;
}
/* decrypt encrypted pre_master_secret */
if (!(pctx = EVP_PKEY_CTX_new(pkey, NULL))) {
SSLerr(SSL_F_GMTLS_PROCESS_CKE_SM2, ERR_R_MALLOC_FAILURE);
return 0;
}
if (!EVP_PKEY_decrypt_init(pctx)
|| !EVP_PKEY_CTX_set_ec_scheme(pctx, NID_sm_scheme)
|| !EVP_PKEY_CTX_set_ec_encrypt_param(pctx, NID_sm3)) {
SSLerr(SSL_F_GMTLS_PROCESS_CKE_SM2, ERR_R_EVP_LIB);
goto end;
}
pmslen = sizeof(pms);
if (!EVP_PKEY_decrypt(pctx, pms, &pmslen,
PACKET_data(&enced_pms), PACKET_remaining(&enced_pms))) {
*al = SSL_AD_DECRYPT_ERROR;
SSLerr(SSL_F_GMTLS_PROCESS_CKE_SM2, SSL_R_DECRYPTION_FAILED);
goto end;
}
if (pmslen != SSL_MAX_MASTER_KEY_LENGTH) {
*al = SSL_AD_DECRYPT_ERROR;
SSLerr(SSL_F_GMTLS_PROCESS_CKE_SM2, SSL_R_DECRYPTION_FAILED);
goto end;
}
ver_good = constant_time_eq_8(pms[0], (unsigned)(s->client_version >> 8)) &
constant_time_eq_8(pms[1], (unsigned)(s->client_version & 0xff));
for (i = 0; i < sizeof(rand_pms); i++) {
pms[i] = constant_time_select_8(ver_good, pms[i], rand_pms[i]);
}
/* generate master_secret */
if (!ssl_generate_master_secret(s, pms, pmslen, 0)) {
SSLerr(SSL_F_GMTLS_PROCESS_CKE_SM2, ERR_R_INTERNAL_ERROR);
goto end;
}
*al = -1;
ret = 1;
end:
EVP_PKEY_CTX_free(pctx);
OPENSSL_cleanse(pms, sizeof(pms));
return ret;
}
static int gmtls_construct_cke_sm9(SSL *s, unsigned char **p, int *l, int *al)
{
int ret = 0;
CERT_SM9 *sm9;
SM9EncParameters encparam;
unsigned char *pms = NULL;
size_t pmslen;
size_t enclen;
unsigned char *d;
*al = SSL_AD_INTERNAL_ERROR;
/* malloc and generate pre_master_secret */
pmslen = SSL_MAX_MASTER_KEY_LENGTH;
if (!(pms = OPENSSL_malloc(pmslen))) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_CKE_SM9, ERR_R_MALLOC_FAILURE);
return 0;
}
pms[0] = s->client_version >> 8;
pms[1] = s->client_version & 0xff;
if (RAND_bytes(pms + 2, pmslen - 2) <= 0) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_CKE_SM9, SSL_R_RANDOM_GENERATOR_ERROR);
goto end;
}
/* encrypt pre_master_secret */
if (!(sm9 = &s->session->ibe)) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_CKE_SM9, ERR_R_INTERNAL_ERROR);
goto end;
}
encparam.kdf_md = EVP_sm3();
encparam.enc_cipher = EVP_get_cipherbynid(
SSL_CIPHER_get_cipher_nid(s->s3->tmp.new_cipher));
encparam.cmac_cipher = NULL;
encparam.cbcmac_cipher = NULL;
encparam.hmac_md = EVP_sm3();
#if 0
if (!SM9_encrypt(sm9->params, &encparam, pms, pmslen,
NULL, &enclen, sm9->id, strlen(sm9->id))) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_CKE_SM9, ERR_R_INTERNAL_ERROR);
goto end;
}
d = *p;
if (!SM9_encrypt(sm9->params, &encparam, pms, pmslen,
&(d[2]), &enclen, sm9->id, strlen(sm9->id))) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_CKE_SM9, ERR_R_INTERNAL_ERROR);
goto end;
}
#endif
/* save pre_master_secret */
s->s3->tmp.pms = pms;
s->s3->tmp.pmslen = pmslen;
pms = NULL;
/* output 2-byte length */
s2n(enclen, d);
*p = d + enclen;
*l = 2 + enclen;
*al = -1;
ret = 1;
end:
OPENSSL_clear_free(pms, pmslen);
return ret;
}
static int gmtls_process_cke_sm9(SSL *s, PACKET *pkt, int *al)
{
int ret = 0;
PACKET enced_pms;
CERT_SM9 *sm9;
SM9EncParameters encparam;
unsigned char *pms = NULL;
size_t pms_len;
*al = SSL_AD_INTERNAL_ERROR;
if (!PACKET_get_length_prefixed_2(pkt, &enced_pms)
|| PACKET_remaining(pkt) != 0) {
*al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_GMTLS_PROCESS_CKE_SM9, SSL_R_LENGTH_MISMATCH);
return 0;
}
if (!(sm9 = &s->cert->ibe)) {
*al = SSL_AD_HANDSHAKE_FAILURE;
SSLerr(SSL_F_GMTLS_PROCESS_CKE_SM9, ERR_R_INTERNAL_ERROR);
return 0;
}
encparam.kdf_md = EVP_sm3();
encparam.enc_cipher = EVP_get_cipherbynid(
SSL_CIPHER_get_cipher_nid(s->s3->tmp.new_cipher));
encparam.cmac_cipher = NULL;
encparam.cbcmac_cipher = NULL;
encparam.hmac_md = EVP_sm3();
#if 0
if (!SM9_decrypt(sm9->params, &encparam,
PACKET_data(&enced_pms), PACKET_remaining(&enced_pms), pms, &pms_len,
sm9->privatekey, sm9->id, strlen(sm9->id))) {
*al = SSL_AD_DECRYPT_ERROR;
SSLerr(SSL_F_GMTLS_PROCESS_CKE_SM9, ERR_R_INTERNAL_ERROR);
return 0;
}
if (pms_len != SSL_MAX_MASTER_KEY_LENGTH) {
*al = SSL_AD_DECRYPT_ERROR;
SSLerr(SSL_F_GMTLS_PROCESS_CKE_SM9, SSL_R_DECRYPTION_FAILED);
goto end;
}
#endif
/* generate master_secret */
if (!ssl_generate_master_secret(s, pms, pms_len, 0)) {
SSLerr(SSL_F_GMTLS_PROCESS_CKE_SM9, ERR_R_INTERNAL_ERROR);
goto end;
}
ret = 1;
end:
return ret;
}
static int gmtls_construct_cke_sm9dhe(SSL *s, unsigned char **p, int *len, int *al)
{
*al = SSL_AD_INTERNAL_ERROR;
SSLerr(SSL_F_GMTLS_CONSTRUCT_CKE_SM9DHE, SSL_R_NOT_IMPLEMENTED);
return 0;
}
static int gmtls_process_cke_sm9dhe(SSL *s, PACKET *pkt, int *al)
{
*al = SSL_AD_INTERNAL_ERROR;
SSLerr(SSL_F_GMTLS_PROCESS_CKE_SM9DHE, SSL_R_NOT_IMPLEMENTED);
return 0;
}
int gmtls_construct_cke_rsa(SSL *s, unsigned char **p, int *len, int *al)
{
#ifndef OPENSSL_NO_RSA
int ret = 0;
unsigned char *q;
X509 *x509;
EVP_PKEY *pkey;
EVP_PKEY_CTX *pctx = NULL;
size_t enclen;
unsigned char *pms = NULL;
size_t pmslen = 0;
/* get peer's encryption cert */
if (!s->session->peer_chain) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_CKE_RSA, ERR_R_INTERNAL_ERROR);
return 0;
}
if (!(x509 = sk_X509_value(s->session->peer_chain, 0))) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_CKE_RSA, ERR_R_INTERNAL_ERROR);
return 0;
}
pkey = X509_get0_pubkey(x509);
if (!EVP_PKEY_get0_RSA(pkey)) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_CKE_RSA, ERR_R_INTERNAL_ERROR);
return 0;
}
/* generate pre_master_secret */
pmslen = SSL_MAX_MASTER_KEY_LENGTH;
if (!(pms = OPENSSL_malloc(pmslen))) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_CKE_RSA, ERR_R_MALLOC_FAILURE);
*al = SSL_AD_INTERNAL_ERROR;
return 0;
}
pms[0] = s->client_version >> 8;
pms[1] = s->client_version & 0xff;
if (RAND_bytes(pms + 2, pmslen - 2) <= 0) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_CKE_RSA, ERR_R_INTERNAL_ERROR);
goto end;
}
q = *p;
*p += 2;
/* encrypt pre_master_secret and output packet */
if (!(pctx = EVP_PKEY_CTX_new(pkey, NULL))) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_CKE_RSA, ERR_R_MALLOC_FAILURE);
goto end;
}
if (EVP_PKEY_encrypt_init(pctx) <= 0
|| EVP_PKEY_encrypt(pctx, NULL, &enclen, pms, pmslen) <= 0) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_CKE_RSA, ERR_R_EVP_LIB);
goto end;
}
if (EVP_PKEY_encrypt(pctx, *p, &enclen, pms, pmslen) <= 0) {
SSLerr(SSL_F_GMTLS_CONSTRUCT_CKE_RSA, SSL_R_BAD_RSA_ENCRYPT);
goto end;
}
*len = enclen;
s2n(*len, q);
*len += 2;
/* save local pre_master_secret */
s->s3->tmp.pms = pms;
s->s3->tmp.pmslen = pmslen;
pms = NULL;
pmslen = 0;
ret = 1;
end:
OPENSSL_clear_free(pms, pmslen);
EVP_PKEY_CTX_free(pctx);
return ret;
#else
SSLerr(SSL_F_GMTLS_CONSTRUCT_CKE_RSA, ERR_R_INTERNAL_ERROR);
*al = SSL_AD_INTERNAL_ERROR;
return 0;
#endif
}
static int gmtls_process_cke_rsa(SSL *s, PACKET *pkt, int *al)
{
#ifndef OPENSSL_NO_RSA
unsigned char rand_premaster_secret[SSL_MAX_MASTER_KEY_LENGTH];
int decrypt_len;
unsigned char decrypt_good, version_good;
size_t j, padding_len;
PACKET enc_premaster;
RSA *rsa = NULL;
unsigned char *rsa_decrypt = NULL;
int ret = 0;
rsa = EVP_PKEY_get0_RSA(s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey);
if (rsa == NULL) {
*al = SSL_AD_HANDSHAKE_FAILURE;
SSLerr(SSL_F_GMTLS_PROCESS_CKE_RSA, SSL_R_MISSING_RSA_CERTIFICATE);
return 0;
}
if (!PACKET_get_length_prefixed_2(pkt, &enc_premaster)
|| PACKET_remaining(pkt) != 0) {
*al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_GMTLS_PROCESS_CKE_RSA, SSL_R_LENGTH_MISMATCH);
return 0;
}
/*
* We want to be sure that the plaintext buffer size makes it safe to
* iterate over the entire size of a premaster secret
* (SSL_MAX_MASTER_KEY_LENGTH). Reject overly short RSA keys because
* their ciphertext cannot accommodate a premaster secret anyway.
*/
if (RSA_size(rsa) < SSL_MAX_MASTER_KEY_LENGTH) {
*al = SSL_AD_INTERNAL_ERROR;
SSLerr(SSL_F_GMTLS_PROCESS_CKE_RSA, RSA_R_KEY_SIZE_TOO_SMALL);
return 0;
}
rsa_decrypt = OPENSSL_malloc(RSA_size(rsa));
if (rsa_decrypt == NULL) {
*al = SSL_AD_INTERNAL_ERROR;
SSLerr(SSL_F_GMTLS_PROCESS_CKE_RSA, ERR_R_MALLOC_FAILURE);
return 0;
}
/*
* We must not leak whether a decryption failure occurs because of
* Bleichenbacher's attack on PKCS #1 v1.5 RSA padding (see RFC 2246,
* section 7.4.7.1). The code follows that advice of the TLS RFC and
* generates a random premaster secret for the case that the decrypt
* fails. See https://tools.ietf.org/html/rfc5246#section-7.4.7.1
*/
if (RAND_bytes(rand_premaster_secret, sizeof(rand_premaster_secret)) <= 0)
goto err;
/*
* Decrypt with no padding. PKCS#1 padding will be removed as part of
* the timing-sensitive code below.
*/
decrypt_len = RSA_private_decrypt(PACKET_remaining(&enc_premaster),
PACKET_data(&enc_premaster),
rsa_decrypt, rsa, RSA_NO_PADDING);
if (decrypt_len < 0)
goto err;
/* Check the padding. See RFC 3447, section 7.2.2. */
/*
* The smallest padded premaster is 11 bytes of overhead. Small keys
* are publicly invalid, so this may return immediately. This ensures
* PS is at least 8 bytes.
*/
if (decrypt_len < 11 + SSL_MAX_MASTER_KEY_LENGTH) {
*al = SSL_AD_DECRYPT_ERROR;
SSLerr(SSL_F_GMTLS_PROCESS_CKE_RSA, SSL_R_DECRYPTION_FAILED);
goto err;
}
padding_len = decrypt_len - SSL_MAX_MASTER_KEY_LENGTH;
decrypt_good = constant_time_eq_int_8(rsa_decrypt[0], 0) &
constant_time_eq_int_8(rsa_decrypt[1], 2);
for (j = 2; j < padding_len - 1; j++) {
decrypt_good &= ~constant_time_is_zero_8(rsa_decrypt[j]);
}
decrypt_good &= constant_time_is_zero_8(rsa_decrypt[padding_len - 1]);
/*
* If the version in the decrypted pre-master secret is correct then
* version_good will be 0xff, otherwise it'll be zero. The
* Klima-Pokorny-Rosa extension of Bleichenbacher's attack
* (http://eprint.iacr.org/2003/052/) exploits the version number
* check as a "bad version oracle". Thus version checks are done in
* constant time and are treated like any other decryption error.
*/
version_good =
constant_time_eq_8(rsa_decrypt[padding_len],
(unsigned)(s->client_version >> 8));
version_good &=
constant_time_eq_8(rsa_decrypt[padding_len + 1],
(unsigned)(s->client_version & 0xff));
/*
* The premaster secret must contain the same version number as the
* ClientHello to detect version rollback attacks (strangely, the
* protocol does not offer such protection for DH ciphersuites).
* However, buggy clients exist that send the negotiated protocol
* version instead if the server does not support the requested
* protocol version. If SSL_OP_TLS_ROLLBACK_BUG is set, tolerate such
* clients.
*/
if (s->options & SSL_OP_TLS_ROLLBACK_BUG) {
unsigned char workaround_good;
workaround_good = constant_time_eq_8(rsa_decrypt[padding_len],
(unsigned)(s->version >> 8));
workaround_good &=
constant_time_eq_8(rsa_decrypt[padding_len + 1],
(unsigned)(s->version & 0xff));
version_good |= workaround_good;
}
/*
* Both decryption and version must be good for decrypt_good to
* remain non-zero (0xff).
*/
decrypt_good &= version_good;
/*
* Now copy rand_premaster_secret over from p using
* decrypt_good_mask. If decryption failed, then p does not
* contain valid plaintext, however, a check above guarantees
* it is still sufficiently large to read from.
*/
for (j = 0; j < sizeof(rand_premaster_secret); j++) {
rsa_decrypt[padding_len + j] = constant_time_select_8(
decrypt_good, rsa_decrypt[padding_len + j],
rand_premaster_secret[j]
);
}
if (!ssl_generate_master_secret(s, rsa_decrypt + padding_len,
sizeof(rand_premaster_secret), 0)) {
*al = SSL_AD_INTERNAL_ERROR;
SSLerr(SSL_F_GMTLS_PROCESS_CKE_RSA, ERR_R_INTERNAL_ERROR);
goto err;
}
ret = 1;
err:
OPENSSL_free(rsa_decrypt);
return ret;
#else
/* Should never happen */
*al = SSL_AD_INTERNAL_ERROR;
SSLerr(SSL_F_GMTLS_PROCESS_CKE_RSA, ERR_R_INTERNAL_ERROR);
return 0;
#endif
}
int gmtls_construct_client_key_exchange(SSL *s)
{
int al = -1;
unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
unsigned char *p = ssl_handshake_start(s);
int l;
if (alg_k & SSL_kRSA) {
if (!gmtls_construct_cke_rsa(s, &p, &l, &al)) {
goto err;
}
} else if (alg_k & SSL_kSM2) {
if (!gmtls_construct_cke_sm2(s, &p, &l, &al)) {
goto err;
}
} else if (alg_k & (SSL_kSM2DHE)) {
if (!gmtls_construct_cke_sm2dhe(s, &p, &l, &al)) {
goto err;
}
} else if (alg_k & SSL_kSM9) {
if (!gmtls_construct_cke_sm9(s, &p, &l, &al)) {
goto err;
}
} else if (alg_k & SSL_kSM9DHE) {
if (!gmtls_construct_cke_sm9dhe(s, &p, &l, &al)) {
goto err;
}
} else {
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
SSLerr(SSL_F_GMTLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
ERR_R_INTERNAL_ERROR);
goto err;
}
if (!ssl_set_handshake_header(s, SSL3_MT_CLIENT_KEY_EXCHANGE, l)) {
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
SSLerr(SSL_F_GMTLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
ERR_R_INTERNAL_ERROR);
goto err;
}
return 1;
err:
if (al != -1)
ssl3_send_alert(s, SSL3_AL_FATAL, al);
OPENSSL_clear_free(s->s3->tmp.pms, s->s3->tmp.pmslen);
s->s3->tmp.pms = NULL;
ossl_statem_set_error(s);
return 0;
}
MSG_PROCESS_RETURN gmtls_process_client_key_exchange(SSL *s, PACKET *pkt)
{
int al = -1;
unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
if (alg_k & SSL_kRSA) {
if (!gmtls_process_cke_rsa(s, pkt, &al)) {
goto err;
}
} else if (alg_k & SSL_kSM2) {
if (!gmtls_process_cke_sm2(s, pkt, &al)) {
goto err;
}
} else if (alg_k & SSL_kSM2DHE) {
if (!gmtls_process_cke_sm2dhe(s, pkt, &al)) {
goto err;
}
} else if (alg_k & SSL_kSM9) {
if (!gmtls_process_cke_sm9(s, pkt, &al)) {
goto err;
}
} else if (alg_k & SSL_kSM9DHE) {
if (!gmtls_process_cke_sm9dhe(s, pkt, &al)) {
goto err;
}
} else {
al = SSL_AD_HANDSHAKE_FAILURE;
SSLerr(SSL_F_GMTLS_PROCESS_CLIENT_KEY_EXCHANGE,
SSL_R_UNKNOWN_CIPHER_TYPE);
goto err;
}
return MSG_PROCESS_CONTINUE_PROCESSING;
err:
ssl3_send_alert(s, SSL3_AL_FATAL, al);
ossl_statem_set_error(s);
return MSG_PROCESS_ERROR;
}