Newer
Older
}
if ((krb5rc = kssl_sget_tkt(kssl_ctx, &enc_ticket, &ttimes,
&kssl_err)) != 0)
Richard Levitte
committed
#ifdef KSSL_DEBUG
printf("kssl_sget_tkt rtn %d [%d]\n",
krb5rc, kssl_err.reason);
if (kssl_err.text)
printf("kssl_err text= %s\n", kssl_err.text);
Richard Levitte
committed
#endif /* KSSL_DEBUG */
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
kssl_err.reason);
goto err;
}
Richard Levitte
committed
/* Note: no authenticator is not considered an error,
** but will return authtime == 0.
*/
if ((krb5rc = kssl_check_authent(kssl_ctx, &authenticator,
&authtime, &kssl_err)) != 0)
{
#ifdef KSSL_DEBUG
printf("kssl_check_authent rtn %d [%d]\n",
krb5rc, kssl_err.reason);
if (kssl_err.text)
printf("kssl_err text= %s\n", kssl_err.text);
#endif /* KSSL_DEBUG */
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
kssl_err.reason);
goto err;
}
if ((krb5rc = kssl_validate_times(authtime, &ttimes)) != 0)
{
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, krb5rc);
}
Richard Levitte
committed
#ifdef KSSL_DEBUG
kssl_ctx_show(kssl_ctx);
Richard Levitte
committed
#endif /* KSSL_DEBUG */
enc = kssl_map_enc(kssl_ctx->enctype);
if (enc == NULL)
goto err;
memset(iv, 0, sizeof iv); /* per RFC 1510 */
if (!EVP_DecryptInit_ex(&ciph_ctx,enc,NULL,kssl_ctx->key,iv))
{
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
SSL_R_DECRYPTION_FAILED);
goto err;
}
if (!EVP_DecryptUpdate(&ciph_ctx, pms,&outl,
{
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
SSL_R_DECRYPTION_FAILED);
goto err;
}
if (outl > SSL_MAX_MASTER_KEY_LENGTH)
{
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
SSL_R_DATA_LENGTH_TOO_LONG);
goto err;
}
if (!EVP_DecryptFinal_ex(&ciph_ctx,&(pms[outl]),&padl))
{
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
SSL_R_DECRYPTION_FAILED);
goto err;
}
outl += padl;
if (outl > SSL_MAX_MASTER_KEY_LENGTH)
{
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
SSL_R_DATA_LENGTH_TOO_LONG);
goto err;
}
if (!((p[0] == (s->client_version>>8)) && (p[1] == (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 random bytes instead of
* the protocol version.
* If SSL_OP_TLS_ROLLBACK_BUG is set, tolerate such clients.
* (Perhaps we should have a separate BUG value for the Kerberos cipher)
*/
if (!((s->options & SSL_OP_TLS_ROLLBACK_BUG) &&
(p[0] == (s->version>>8)) && (p[1] == (s->version & 0xff))))
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
SSL_AD_DECODE_ERROR);
goto err;
}
}
EVP_CIPHER_CTX_cleanup(&ciph_ctx);
s->session->master_key_length=
s->method->ssl3_enc->generate_master_secret(s,
s->session->master_key, pms, outl);
if (kssl_ctx->client_princ)
{
size_t len = strlen(kssl_ctx->client_princ);
if ( len < SSL_MAX_KRB5_PRINCIPAL_LENGTH )
{
s->session->krb5_client_princ_len = len;
memcpy(s->session->krb5_client_princ,kssl_ctx->client_princ,len);
}
}
/* Was doing kssl_ctx_free() here,
** but it caused problems for apache.
** kssl_ctx = kssl_ctx_free(kssl_ctx);
** if (s->kssl_ctx) s->kssl_ctx = NULL;
*/
}
Richard Levitte
committed
else
#endif /* OPENSSL_NO_KRB5 */
if (alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe))
const EC_KEY *tkey;
const EC_GROUP *group;
const BIGNUM *priv_key;
/* initialize structures for server's ECDH key pair */
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
}
/* Let's get server private key and group information */
if (alg_k & (SSL_kECDHr|SSL_kECDHe))
/* use the certificate */
tkey = s->cert->pkeys[SSL_PKEY_ECC].privatekey->pkey.ec;
}
else
{
/* use the ephermeral values we saved when
* generating the ServerKeyExchange msg.
*/
tkey = s->s3->tmp.ecdh;
}
group = EC_KEY_get0_group(tkey);
priv_key = EC_KEY_get0_private_key(tkey);
if (!EC_KEY_set_group(srvr_ecdh, group) ||
!EC_KEY_set_private_key(srvr_ecdh, priv_key))
{
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
ERR_R_EC_LIB);
goto err;
if ((clnt_ecpoint = EC_POINT_new(group)) == NULL)
{
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
ERR_R_MALLOC_FAILURE);
goto err;
}
if (n == 0L)
{
/* Client Publickey was in Client Certificate */
if (alg_k & SSL_kEECDH)
{
al=SSL_AD_HANDSHAKE_FAILURE;
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_MISSING_TMP_ECDH_KEY);
goto f_err;
}
if (((clnt_pub_pkey=X509_get_pubkey(s->session->peer))
(clnt_pub_pkey->type != EVP_PKEY_EC))
/* XXX: For now, we do not support client
* authentication using ECDH certificates
* so this branch (n == 0L) of the code is
* never executed. When that support is
* added, we ought to ensure the key
* received in the certificate is
* authorized for key agreement.
* ECDH_compute_key implicitly checks that
* the two ECDH shares are for the same
* group.
*/
al=SSL_AD_HANDSHAKE_FAILURE;
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
goto f_err;
}
if (EC_POINT_copy(clnt_ecpoint,
EC_KEY_get0_public_key(clnt_pub_pkey->pkey.ec)) == 0)
{
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
ERR_R_EC_LIB);
goto err;
}
ret = 2; /* Skip certificate verify processing */
}
else
{
/* Get client's public key from encoded point
* in the ClientKeyExchange message.
*/
if ((bn_ctx = BN_CTX_new()) == NULL)
{
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
ERR_R_MALLOC_FAILURE);
goto err;
}
/* Get encoded point length */
i = *p;
if (EC_POINT_oct2point(group,
clnt_ecpoint, p, i, bn_ctx) == 0)
{
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
ERR_R_EC_LIB);
goto err;
}
/* p is pointing to somewhere in the buffer
* currently, so set it to the start
*/
p=(unsigned char *)s->init_buf->data;
}
if (field_size <= 0)
{
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
ERR_R_ECDH_LIB);
goto err;
}
i = ECDH_compute_key(p, (field_size+7)/8, clnt_ecpoint, srvr_ecdh, NULL);
if (i <= 0)
{
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
goto err;
}
EVP_PKEY_free(clnt_pub_pkey);
EC_POINT_free(clnt_ecpoint);
if (srvr_ecdh != NULL)
EC_KEY_free(srvr_ecdh);
BN_CTX_free(bn_ctx);
/* Compute the master secret */
s->session->master_key_length = s->method->ssl3_enc-> \
generate_master_secret(s, s->session->master_key, p, i);
OPENSSL_cleanse(p, i);
return (ret);
#endif
#ifndef OPENSSL_NO_PSK
if (alg_k & SSL_kPSK)
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
{
unsigned char *t = NULL;
unsigned char psk_or_pre_ms[PSK_MAX_PSK_LEN*2+4];
unsigned int pre_ms_len = 0, psk_len = 0;
int psk_err = 1;
char tmp_id[PSK_MAX_IDENTITY_LEN+1];
al=SSL_AD_HANDSHAKE_FAILURE;
n2s(p,i);
if (n != i+2)
{
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
SSL_R_LENGTH_MISMATCH);
goto psk_err;
}
if (i > PSK_MAX_IDENTITY_LEN)
{
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
SSL_R_DATA_LENGTH_TOO_LONG);
goto psk_err;
}
if (s->psk_server_callback == NULL)
{
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
SSL_R_PSK_NO_SERVER_CB);
goto psk_err;
}
/* Create guaranteed NULL-terminated identity
* string for the callback */
memcpy(tmp_id, p, i);
memset(tmp_id+i, 0, PSK_MAX_IDENTITY_LEN+1-i);
psk_len = s->psk_server_callback(s, tmp_id,
psk_or_pre_ms, sizeof(psk_or_pre_ms));
OPENSSL_cleanse(tmp_id, PSK_MAX_IDENTITY_LEN+1);
if (psk_len > PSK_MAX_PSK_LEN)
{
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
ERR_R_INTERNAL_ERROR);
goto psk_err;
}
else if (psk_len == 0)
{
/* PSK related to the given identity not found */
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
SSL_R_PSK_IDENTITY_NOT_FOUND);
al=SSL_AD_UNKNOWN_PSK_IDENTITY;
goto psk_err;
}
/* create PSK pre_master_secret */
pre_ms_len=2+psk_len+2+psk_len;
t = psk_or_pre_ms;
memmove(psk_or_pre_ms+psk_len+4, psk_or_pre_ms, psk_len);
s2n(psk_len, t);
memset(t, 0, psk_len);
t+=psk_len;
s2n(psk_len, t);
if (s->session->psk_identity != NULL)
OPENSSL_free(s->session->psk_identity);
s->session->psk_identity = BUF_strdup((char *)p);
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
if (s->session->psk_identity == NULL)
{
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
ERR_R_MALLOC_FAILURE);
goto psk_err;
}
if (s->session->psk_identity_hint != NULL)
OPENSSL_free(s->session->psk_identity_hint);
s->session->psk_identity_hint = BUF_strdup(s->ctx->psk_identity_hint);
if (s->ctx->psk_identity_hint != NULL &&
s->session->psk_identity_hint == NULL)
{
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
ERR_R_MALLOC_FAILURE);
goto psk_err;
}
s->session->master_key_length=
s->method->ssl3_enc->generate_master_secret(s,
s->session->master_key, psk_or_pre_ms, pre_ms_len);
psk_err = 0;
psk_err:
OPENSSL_cleanse(psk_or_pre_ms, sizeof(psk_or_pre_ms));
if (psk_err != 0)
goto f_err;
al=SSL_AD_HANDSHAKE_FAILURE;
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
SSL_R_UNKNOWN_CIPHER_TYPE);
goto f_err;
}
return(1);
f_err:
ssl3_send_alert(s,SSL3_AL_FATAL,al);
#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_ECDH)
EVP_PKEY_free(clnt_pub_pkey);
EC_POINT_free(clnt_ecpoint);
if (srvr_ecdh != NULL)
EC_KEY_free(srvr_ecdh);
BN_CTX_free(bn_ctx);
return(-1);
}
{
EVP_PKEY *pkey=NULL;
unsigned char *p;
int al,ok,ret=0;
long n;
int type=0,i,j;
X509 *peer;
SSL3_ST_SR_CERT_VRFY_A,
SSL3_ST_SR_CERT_VRFY_B,
-1,
514, /* 514? */
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
&ok);
if (!ok) return((int)n);
if (s->session->peer != NULL)
{
peer=s->session->peer;
pkey=X509_get_pubkey(peer);
type=X509_certificate_type(peer,pkey);
}
else
{
peer=NULL;
pkey=NULL;
}
if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE_VERIFY)
{
s->s3->tmp.reuse_message=1;
if ((peer != NULL) && (type | EVP_PKT_SIGN))
{
al=SSL_AD_UNEXPECTED_MESSAGE;
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_MISSING_VERIFY_MESSAGE);
goto f_err;
}
ret=1;
goto end;
}
if (peer == NULL)
{
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_NO_CLIENT_CERT_RECEIVED);
al=SSL_AD_UNEXPECTED_MESSAGE;
goto f_err;
}
if (!(type & EVP_PKT_SIGN))
{
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE);
al=SSL_AD_ILLEGAL_PARAMETER;
goto f_err;
}
if (s->s3->change_cipher_spec)
{
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_CCS_RECEIVED_EARLY);
al=SSL_AD_UNEXPECTED_MESSAGE;
goto f_err;
}
/* we now have a signature that we need to verify */
p=(unsigned char *)s->init_msg;
n2s(p,i);
n-=2;
if (i > n)
{
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_LENGTH_MISMATCH);
al=SSL_AD_DECODE_ERROR;
goto f_err;
}
j=EVP_PKEY_size(pkey);
if ((i > j) || (n > j) || (n <= 0))
{
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_WRONG_SIGNATURE_SIZE);
al=SSL_AD_DECODE_ERROR;
goto f_err;
}
#ifndef OPENSSL_NO_RSA
if (pkey->type == EVP_PKEY_RSA)
{
i=RSA_verify(NID_md5_sha1, s->s3->tmp.cert_verify_md,
Dr. Stephen Henson
committed
MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH, p, i,
pkey->pkey.rsa);
al=SSL_AD_DECRYPT_ERROR;
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_BAD_RSA_DECRYPT);
goto f_err;
}
Dr. Stephen Henson
committed
if (i == 0)
al=SSL_AD_DECRYPT_ERROR;
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_BAD_RSA_SIGNATURE);
goto f_err;
}
}
else
#endif
#ifndef OPENSSL_NO_DSA
if (pkey->type == EVP_PKEY_DSA)
{
j=DSA_verify(pkey->save_type,
&(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH]),
SHA_DIGEST_LENGTH,p,i,pkey->pkey.dsa);
if (j <= 0)
{
/* bad signature */
al=SSL_AD_DECRYPT_ERROR;
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_BAD_DSA_SIGNATURE);
goto f_err;
}
}
else
if (pkey->type == EVP_PKEY_EC)
{
j=ECDSA_verify(pkey->save_type,
&(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH]),
if (j <= 0)
{
/* bad signature */
al=SSL_AD_DECRYPT_ERROR;
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,
SSL_R_BAD_ECDSA_SIGNATURE);
goto f_err;
}
}
else
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,ERR_R_INTERNAL_ERROR);
al=SSL_AD_UNSUPPORTED_CERTIFICATE;
goto f_err;
}
ret=1;
if (0)
{
f_err:
ssl3_send_alert(s,SSL3_AL_FATAL,al);
}
end:
EVP_PKEY_free(pkey);
return(ret);
}
{
int i,ok,al,ret= -1;
X509 *x=NULL;
unsigned long l,nc,llen,n;
const unsigned char *p,*q;
unsigned char *d;
SSL3_ST_SR_CERT_A,
SSL3_ST_SR_CERT_B,
-1,
s->max_cert_list,
&ok);
if (!ok) return((int)n);
if (s->s3->tmp.message_type == SSL3_MT_CLIENT_KEY_EXCHANGE)
{
if ( (s->verify_mode & SSL_VERIFY_PEER) &&
(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT))
{
SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
al=SSL_AD_HANDSHAKE_FAILURE;
goto f_err;
}
/* If tls asked for a client cert, the client must return a 0 list */
if ((s->version > SSL3_VERSION) && s->s3->tmp.cert_request)
{
SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST);
al=SSL_AD_UNEXPECTED_MESSAGE;
goto f_err;
}
s->s3->tmp.reuse_message=1;
return(1);
}
if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE)
{
al=SSL_AD_UNEXPECTED_MESSAGE;
SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_WRONG_MESSAGE_TYPE);
goto f_err;
}
p=d=(unsigned char *)s->init_msg;
{
SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,ERR_R_MALLOC_FAILURE);
goto err;
}
n2l3(p,llen);
if (llen+3 != n)
{
al=SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_LENGTH_MISMATCH);
goto f_err;
}
for (nc=0; nc<llen; )
{
n2l3(p,l);
if ((l+nc+3) > llen)
{
al=SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_CERT_LENGTH_MISMATCH);
goto f_err;
}
q=p;
x=d2i_X509(NULL,&p,l);
if (x == NULL)
{
SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,ERR_R_ASN1_LIB);
goto err;
}
if (p != (q+l))
{
al=SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_CERT_LENGTH_MISMATCH);
goto f_err;
}
{
SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,ERR_R_MALLOC_FAILURE);
goto err;
}
x=NULL;
nc+=l+3;
}
/* TLS does not mind 0 certs returned */
if (s->version == SSL3_VERSION)
{
al=SSL_AD_HANDSHAKE_FAILURE;
SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_NO_CERTIFICATES_RETURNED);
goto f_err;
}
/* Fail for TLS only if we required a certificate */
else if ((s->verify_mode & SSL_VERIFY_PEER) &&
(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT))
{
SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
al=SSL_AD_HANDSHAKE_FAILURE;
goto f_err;
}
i=ssl_verify_cert_chain(s,sk);
if (!i)
{
al=ssl_verify_alarm_type(s->verify_result);
SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_NO_CERTIFICATE_RETURNED);
goto f_err;
}
if (s->session->peer != NULL) /* This should not be needed */
X509_free(s->session->peer);
s->session->verify_result = s->verify_result;
/* With the current implementation, sess_cert will always be NULL
* when we arrive here. */
if (s->session->sess_cert == NULL)
{
s->session->sess_cert = ssl_sess_cert_new();
if (s->session->sess_cert == NULL)
{
SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE, ERR_R_MALLOC_FAILURE);
goto err;
}
}
if (s->session->sess_cert->cert_chain != NULL)
sk_X509_pop_free(s->session->sess_cert->cert_chain, X509_free);
s->session->sess_cert->cert_chain=sk;
/* Inconsistency alert: cert_chain does *not* include the
* peer's own certificate, while we do include it in s3_clnt.c */
ret=1;
if (0)
{
f_err:
ssl3_send_alert(s,SSL3_AL_FATAL,al);
}
err:
if (x != NULL) X509_free(x);
if (sk != NULL) sk_X509_pop_free(sk,X509_free);
return(ret);
}
{
unsigned long l;
X509 *x;
if (s->state == SSL3_ST_SW_CERT_A)
{
x=ssl_get_server_send_cert(s);
if (x == NULL)
{
/* VRS: allow null cert if auth == KRB5 */
if ((s->s3->tmp.new_cipher->algorithm_auth != SSL_aKRB5) ||
(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kKRB5))
{
SSLerr(SSL_F_SSL3_SEND_SERVER_CERTIFICATE,ERR_R_INTERNAL_ERROR);
return(0);
}
}
l=ssl3_output_cert_chain(s,x);
s->state=SSL3_ST_SW_CERT_B;
s->init_num=(int)l;
s->init_off=0;
}
/* SSL3_ST_SW_CERT_B */
return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
}
Dr. Stephen Henson
committed
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
int ssl3_send_newsession_ticket(SSL *s)
{
if (s->state == SSL3_ST_SW_SESSION_TICKET_A)
{
unsigned char *p, *senc, *macstart;
int len, slen;
unsigned int hlen;
EVP_CIPHER_CTX ctx;
HMAC_CTX hctx;
/* get session encoding length */
slen = i2d_SSL_SESSION(s->session, NULL);
/* Some length values are 16 bits, so forget it if session is
* too long
*/
if (slen > 0xFF00)
return -1;
/* Grow buffer if need be: the length calculation is as
* follows 1 (size of message name) + 3 (message length
* bytes) + 4 (ticket lifetime hint) + 2 (ticket length) +
* 16 (key name) + max_iv_len (iv length) +
* session_length + max_enc_block_size (max encrypted session
* length) + max_md_size (HMAC).
*/
if (!BUF_MEM_grow(s->init_buf,
26 + EVP_MAX_IV_LENGTH + EVP_MAX_BLOCK_LENGTH +
EVP_MAX_MD_SIZE + slen))
return -1;
senc = OPENSSL_malloc(slen);
if (!senc)
return -1;
p = senc;
i2d_SSL_SESSION(s->session, &p);
p=(unsigned char *)s->init_buf->data;
/* do the header */
*(p++)=SSL3_MT_NEWSESSION_TICKET;
/* Skip message length for now */
p += 3;
l2n(s->session->tlsext_tick_lifetime_hint, p);
/* Skip ticket length for now */
p += 2;
/* Output key name */
macstart = p;
memcpy(p, s->ctx->tlsext_tick_key_name, 16);
p += 16;
/* Generate and output IV */
RAND_pseudo_bytes(p, 16);
EVP_CIPHER_CTX_init(&ctx);
/* Encrypt session data */
EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
s->ctx->tlsext_tick_aes_key, p);
p += 16;
EVP_EncryptUpdate(&ctx, p, &len, senc, slen);
p += len;
EVP_EncryptFinal(&ctx, p, &len);
p += len;
EVP_CIPHER_CTX_cleanup(&ctx);
HMAC_CTX_init(&hctx);
HMAC_Init_ex(&hctx, s->ctx->tlsext_tick_hmac_key, 16,
EVP_sha1(), NULL);
HMAC_Update(&hctx, macstart, p - macstart);
HMAC_Final(&hctx, p, &hlen);
HMAC_CTX_cleanup(&hctx);
p += hlen;
/* Now write out lengths: p points to end of data written */
/* Total length */
len = p - (unsigned char *)s->init_buf->data;
p=(unsigned char *)s->init_buf->data + 1;
l2n3(len - 4, p); /* Message length */
p += 4;
s2n(len - 10, p); /* Ticket length */
/* number of bytes to write */
s->init_num= len;
s->state=SSL3_ST_SW_SESSION_TICKET_B;
s->init_off=0;
OPENSSL_free(senc);
}
/* SSL3_ST_SW_SESSION_TICKET_B */
return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
}
#endif