1898Skais /* 2898Skais * CDDL HEADER START 3898Skais * 4898Skais * The contents of this file are subject to the terms of the 51724Skrishna * Common Development and Distribution License (the "License"). 61724Skrishna * You may not use this file except in compliance with the License. 7898Skais * 8898Skais * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9898Skais * or http://www.opensolaris.org/os/licensing. 10898Skais * See the License for the specific language governing permissions 11898Skais * and limitations under the License. 12898Skais * 13898Skais * When distributing Covered Code, include this CDDL HEADER in each 14898Skais * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15898Skais * If applicable, add the following below this CDDL HEADER, with the 16898Skais * fields enclosed by brackets "[]" replaced with your own identifying 17898Skais * information: Portions Copyright [yyyy] [name of copyright owner] 18898Skais * 19898Skais * CDDL HEADER END 20898Skais */ 21898Skais /* 22*4859Skrishna * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23898Skais * Use is subject to license terms. 24898Skais */ 25898Skais 26898Skais #pragma ident "%Z%%M% %I% %E% SMI" 27898Skais 28898Skais #include <sys/types.h> 29898Skais #include <sys/stream.h> 30898Skais #include <sys/strsubr.h> 31898Skais #include <sys/stropts.h> 32898Skais #include <sys/strsun.h> 33898Skais #define _SUN_TPI_VERSION 2 34898Skais #include <sys/ddi.h> 35898Skais #include <sys/sunddi.h> 36898Skais #include <sys/cmn_err.h> 37898Skais #include <sys/debug.h> 38898Skais #include <sys/vtrace.h> 39898Skais #include <sys/kmem.h> 40898Skais #include <sys/cpuvar.h> 41898Skais #include <sys/atomic.h> 42898Skais #include <sys/sysmacros.h> 43898Skais 44898Skais #include <sys/errno.h> 45898Skais #include <sys/isa_defs.h> 46898Skais #include <sys/md5.h> 47898Skais #include <sys/sha1.h> 48898Skais #include <sys/random.h> 49898Skais #include <inet/common.h> 50898Skais #include <netinet/in.h> 51898Skais 52898Skais #include <sys/systm.h> 53898Skais #include <sys/param.h> 54898Skais 55898Skais #include "ksslimpl.h" 56898Skais #include "ksslapi.h" 57898Skais #include "ksslproto.h" 58898Skais #include "kssldebug.h" 59898Skais 60898Skais static ssl3CipherSuiteDef cipher_suite_defs[] = { 61898Skais {SSL_RSA_WITH_RC4_128_SHA, cipher_rc4, mac_sha, 72}, 62898Skais {SSL_RSA_WITH_RC4_128_MD5, cipher_rc4, mac_md5, 64}, 63898Skais {SSL_RSA_WITH_DES_CBC_SHA, cipher_des, mac_sha, 72}, 64898Skais {SSL_RSA_WITH_3DES_EDE_CBC_SHA, cipher_3des, mac_sha, 104}, 65898Skais {SSL_RSA_WITH_NULL_SHA, cipher_null, mac_sha, 40} 66898Skais }; 67898Skais 68898Skais static int cipher_suite_defs_nentries = 69898Skais sizeof (cipher_suite_defs) / sizeof (cipher_suite_defs[0]); 70898Skais 71898Skais static KSSLMACDef mac_defs[] = { /* indexed by SSL3MACAlgorithm */ 72898Skais /* macsz padsz HashInit HashUpdate HashFinal */ 73898Skais 74898Skais {MD5_HASH_LEN, SSL3_MD5_PAD_LEN, 75898Skais (hashinit_func_t)MD5Init, (hashupdate_func_t)MD5Update, 76898Skais (hashfinal_func_t)MD5Final}, 77898Skais 78898Skais {SHA1_HASH_LEN, SSL3_SHA1_PAD_LEN, 79898Skais (hashinit_func_t)SHA1Init, (hashupdate_func_t)SHA1Update, 80898Skais (hashfinal_func_t)SHA1Final}, 81898Skais }; 82898Skais 83898Skais static uchar_t kssl_pad_1[60] = { 84898Skais 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 85898Skais 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 86898Skais 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 87898Skais 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 88898Skais 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 89898Skais 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 90898Skais 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 91898Skais 0x36, 0x36, 0x36, 0x36 92898Skais }; 93898Skais static uchar_t kssl_pad_2[60] = { 94898Skais 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 95898Skais 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 96898Skais 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 97898Skais 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 98898Skais 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 99898Skais 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 100898Skais 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 101898Skais 0x5c, 0x5c, 0x5c, 0x5c 102898Skais }; 103898Skais 104898Skais int kssl_debug; 105898Skais int kssl_cache_count; 106898Skais static boolean_t kssl_synchronous = B_FALSE; 107898Skais 108898Skais static void kssl_update_handshake_hashes(ssl_t *, uchar_t *, uint_t); 109898Skais static int kssl_compute_handshake_hashes(ssl_t *, SSL3Hashes *, uint32_t); 110898Skais static int kssl_handle_client_hello(ssl_t *, mblk_t *, int); 111898Skais static int kssl_handle_client_key_exchange(ssl_t *, mblk_t *, int, 112898Skais kssl_callback_t, void *); 113898Skais static int kssl_send_server_hello(ssl_t *); 114898Skais static int kssl_send_certificate_and_server_hello_done(ssl_t *); 115898Skais static int kssl_send_change_cipher_specs(ssl_t *); 116898Skais static int kssl_send_finished(ssl_t *, int); 117898Skais static int kssl_handle_finished(ssl_t *, mblk_t *, int); 118898Skais static void kssl_get_hello_random(uchar_t *); 119898Skais static uchar_t *kssl_rsa_unwrap(uchar_t *, size_t *); 120898Skais static void kssl_cache_sid(sslSessionID *, kssl_entry_t *); 121898Skais static void kssl_lookup_sid(sslSessionID *, uchar_t *, ipaddr_t, 122898Skais kssl_entry_t *); 123898Skais static int kssl_generate_tls_ms(ssl_t *, uchar_t *, size_t); 124898Skais static void kssl_generate_ssl_ms(ssl_t *, uchar_t *, size_t); 125898Skais static int kssl_generate_tls_keyblock(ssl_t *); 126898Skais static void kssl_generate_keyblock(ssl_t *); 127898Skais static void kssl_ssl3_key_material_derive_step(ssl_t *, uchar_t *, size_t, 128898Skais int, uchar_t *, int); 129898Skais static int kssl_tls_PRF(ssl_t *, uchar_t *, size_t, 130898Skais uchar_t *, size_t, uchar_t *, size_t, uchar_t *, size_t); 131898Skais static int kssl_tls_P_hash(crypto_mechanism_t *, crypto_key_t *, 132898Skais size_t, uchar_t *, size_t, uchar_t *, size_t, uchar_t *, size_t); 133898Skais static void kssl_cke_done(void *, int); 134898Skais 135898Skais #define MAX_TLS_KEYBLOCK_SIZE 160 /* more than enough for largest TLS key */ 136898Skais 137898Skais #define HMAC_INIT(m, k, c) \ 138898Skais rv = crypto_mac_init(m, k, NULL, c, NULL); if (CRYPTO_ERR(rv)) goto end; 139898Skais 140898Skais #define HMAC_UPDATE(c, d, l) \ 141898Skais dd.cd_raw.iov_base = (char *)d; \ 142898Skais dd.cd_length = dd.cd_raw.iov_len = l; \ 143898Skais rv = crypto_mac_update(c, &dd, NULL); if (CRYPTO_ERR(rv)) goto end; 144898Skais 145898Skais #define HMAC_FINAL(c, d, l) \ 146898Skais mac.cd_raw.iov_base = (char *)d; \ 147898Skais mac.cd_length = mac.cd_raw.iov_len = l; \ 148898Skais rv = crypto_mac_final(c, &mac, NULL); if (CRYPTO_ERR(rv)) goto end; 149898Skais 150*4859Skrishna /* 151*4859Skrishna * This hack can go away once we have SSL3 MAC support by KCF 152*4859Skrishna * software providers (See 4873559). 153*4859Skrishna */ 154*4859Skrishna extern int kcf_md5_threshold; 155*4859Skrishna 156898Skais int 157898Skais kssl_compute_record_mac( 158898Skais ssl_t *ssl, 159898Skais int direction, 160898Skais uint64_t seq_num, 161898Skais SSL3ContentType ct, 162898Skais uchar_t *versionp, 163898Skais uchar_t *buf, 164898Skais int len, 165898Skais uchar_t *digest) 166898Skais { 167898Skais KSSL_HASHCTX mac_ctx; 168898Skais KSSL_HASHCTX *ctx = &mac_ctx; 169898Skais uchar_t temp[16], *p; 170898Skais KSSLCipherSpec *spec; 171*4859Skrishna boolean_t hash_use_ok = B_FALSE; 172898Skais int rv = 0; 173898Skais 174898Skais spec = &ssl->spec[direction]; 175898Skais 176898Skais if (spec->mac_hashsz == 0) { 177898Skais return (1); 178898Skais } 179898Skais 180898Skais p = temp; 181898Skais 182898Skais *p++ = (seq_num >> 56) & 0xff; 183898Skais *p++ = (seq_num >> 48) & 0xff; 184898Skais *p++ = (seq_num >> 40) & 0xff; 185898Skais *p++ = (seq_num >> 32) & 0xff; 186898Skais *p++ = (seq_num >> 24) & 0xff; 187898Skais *p++ = (seq_num >> 16) & 0xff; 188898Skais *p++ = (seq_num >> 8) & 0xff; 189898Skais *p++ = (seq_num) & 0xff; 190898Skais *p++ = (uchar_t)ct; 191898Skais if (IS_TLS(ssl)) { 192898Skais *p++ = versionp[0]; 193898Skais *p++ = versionp[1]; 194898Skais } 195898Skais *p++ = (len >> 8) & 0xff; 196898Skais *p++ = (len) & 0xff; 197898Skais 198*4859Skrishna if (IS_TLS(ssl) || (spec->hmac_mech.cm_type != CRYPTO_MECH_INVALID && 199*4859Skrishna len >= kcf_md5_threshold)) { 200898Skais crypto_data_t dd, mac; 201*4859Skrishna struct uio uio_pt; 202*4859Skrishna struct iovec iovarray_pt[2]; 203*4859Skrishna 204*4859Skrishna /* init the array of iovecs for use in the uio struct */ 205*4859Skrishna iovarray_pt[0].iov_base = (char *)temp; 206*4859Skrishna iovarray_pt[0].iov_len = (p - temp); 207*4859Skrishna iovarray_pt[1].iov_base = (char *)buf; 208*4859Skrishna iovarray_pt[1].iov_len = len; 209898Skais 210*4859Skrishna /* init the uio struct for use in the crypto_data_t struct */ 211*4859Skrishna bzero(&uio_pt, sizeof (uio_pt)); 212*4859Skrishna uio_pt.uio_iov = iovarray_pt; 213*4859Skrishna uio_pt.uio_iovcnt = 2; 214*4859Skrishna uio_pt.uio_segflg = UIO_SYSSPACE; 215*4859Skrishna 216*4859Skrishna dd.cd_format = CRYPTO_DATA_UIO; 217898Skais dd.cd_offset = 0; 218*4859Skrishna dd.cd_length = (p - temp) + len; 219*4859Skrishna dd.cd_miscdata = NULL; 220*4859Skrishna dd.cd_uio = &uio_pt; 221*4859Skrishna 222898Skais mac.cd_format = CRYPTO_DATA_RAW; 223898Skais mac.cd_offset = 0; 224*4859Skrishna mac.cd_raw.iov_base = (char *)digest; 225*4859Skrishna mac.cd_length = mac.cd_raw.iov_len = spec->mac_hashsz; 226898Skais 227*4859Skrishna /* 228*4859Skrishna * The calling context can tolerate a blocking call here. 229*4859Skrishna * For outgoing traffic, we are in user context 230*4859Skrishna * when called from strsock_kssl_output(). For incoming 231*4859Skrishna * traffic past the SSL handshake, we are in user 232*4859Skrishna * context when called from strsock_kssl_input(). During the 233*4859Skrishna * SSL handshake, we are called for client_finished message 234*4859Skrishna * handling from a squeue worker thread that gets scheduled 235*4859Skrishna * by an squeue_fill() call. This thread is not in interrupt 236*4859Skrishna * context and so can block. 237*4859Skrishna */ 238*4859Skrishna rv = crypto_mac(&spec->hmac_mech, &dd, &spec->hmac_key, 239*4859Skrishna NULL, &mac, NULL); 240*4859Skrishna 241898Skais if (CRYPTO_ERR(rv)) { 242*4859Skrishna hash_use_ok = (rv == CRYPTO_MECH_NOT_SUPPORTED && 243*4859Skrishna !IS_TLS(ssl)); 244*4859Skrishna if (!hash_use_ok) { 245898Skais #ifdef DEBUG 246*4859Skrishna cmn_err(CE_WARN, "kssl_compute_record_mac - " 247*4859Skrishna "crypto_mac error 0x%0x", rv); 248898Skais #endif /* DEBUG */ 249*4859Skrishna KSSL_COUNTER(compute_mac_failure, 1); 250*4859Skrishna } 251898Skais } 252*4859Skrishna } else 253*4859Skrishna hash_use_ok = B_TRUE; 254*4859Skrishna 255*4859Skrishna if (hash_use_ok) { 256898Skais bcopy(&(ssl->mac_ctx[direction][0]), ctx, 257898Skais sizeof (KSSL_HASHCTX)); 258898Skais spec->MAC_HashUpdate((void *)ctx, temp, p - temp); 259898Skais spec->MAC_HashUpdate((void *)ctx, buf, len); 260898Skais spec->MAC_HashFinal(digest, (void *)ctx); 261898Skais 262898Skais bcopy(&(ssl->mac_ctx[direction][1]), ctx, 263898Skais sizeof (KSSL_HASHCTX)); 264898Skais spec->MAC_HashUpdate((void *)ctx, digest, spec->mac_hashsz); 265898Skais spec->MAC_HashFinal(digest, (void *)ctx); 266898Skais } 267898Skais 268898Skais return (rv); 269898Skais } 270898Skais 271898Skais /* 272898Skais * Handles handshake messages. 273898Skais * Messages to be replied are returned in handshake_sendbuf. 274898Skais */ 275898Skais int 276898Skais kssl_handle_handshake_message(ssl_t *ssl, mblk_t *mp, int *err, 277898Skais kssl_callback_t cbfn, void *arg) 278898Skais { 279898Skais uint32_t msglen; 280898Skais uchar_t msghdr[4]; 281898Skais 282898Skais ASSERT(ssl->msg.state == MSG_BODY); 283898Skais ASSERT(ssl->msg.msglen_bytes == 3); 284898Skais ASSERT(mp->b_wptr >= mp->b_rptr + ssl->msg.msglen); 285898Skais 286898Skais ssl->sslcnt++; 287898Skais msglen = ssl->msg.msglen; 288898Skais 289898Skais if (ssl->msg.type == client_hello) { 290898Skais MD5Init(&ssl->hs_md5); 291898Skais SHA1Init(&ssl->hs_sha1); 292898Skais } 293898Skais 294898Skais if (ssl->msg.type == finished && ssl->resumed == B_FALSE) { 295898Skais if (kssl_compute_handshake_hashes(ssl, &ssl->hs_hashes, 296898Skais sender_client) != 0) { 297898Skais *err = SSL_MISS; 298898Skais return (0); 299898Skais } 300898Skais } 301898Skais 302898Skais if (ssl->msg.type != finished || ssl->resumed == B_FALSE) { 303898Skais msghdr[0] = (uchar_t)ssl->msg.type; 304898Skais 305898Skais msghdr[1] = (uchar_t)(msglen >> 16); 306898Skais msghdr[2] = (uchar_t)(msglen >> 8); 307898Skais msghdr[3] = (uchar_t)(msglen); 308898Skais kssl_update_handshake_hashes(ssl, msghdr, 4); 309898Skais kssl_update_handshake_hashes(ssl, mp->b_rptr, msglen); 310898Skais } 311898Skais 312898Skais ssl->msg.state = MSG_INIT; 313898Skais ssl->msg.msglen = 0; 314898Skais ssl->msg.msglen_bytes = 0; 315898Skais 316898Skais switch (ssl->msg.type) { 317898Skais case client_hello: 318898Skais if (ssl->hs_waitstate != wait_client_hello) { 319898Skais kssl_send_alert(ssl, alert_fatal, 320898Skais unexpected_message); 321898Skais *err = EBADMSG; 322898Skais ssl->activeinput = B_FALSE; 323898Skais return (1); 324898Skais } 325898Skais *err = kssl_handle_client_hello(ssl, mp, msglen); 326898Skais if (*err == SSL_MISS) { 327898Skais ssl->activeinput = B_FALSE; 328898Skais return (0); 329898Skais } 330898Skais return (1); 331898Skais case client_key_exchange: 332898Skais if (ssl->hs_waitstate != wait_client_key) { 333898Skais kssl_send_alert(ssl, alert_fatal, 334898Skais unexpected_message); 335898Skais *err = EBADMSG; 336898Skais ssl->activeinput = B_FALSE; 337898Skais return (1); 338898Skais } 339898Skais *err = kssl_handle_client_key_exchange(ssl, mp, 340898Skais msglen, cbfn, arg); 341898Skais return (1); 342898Skais case finished: 343898Skais if (ssl->hs_waitstate != wait_finished) { 344898Skais kssl_send_alert(ssl, alert_fatal, 345898Skais unexpected_message); 346898Skais *err = EBADMSG; 347898Skais ssl->activeinput = B_FALSE; 348898Skais return (1); 349898Skais } 350898Skais *err = kssl_handle_finished(ssl, mp, msglen); 351898Skais return (1); 352898Skais default: 353898Skais kssl_send_alert(ssl, alert_fatal, unexpected_message); 354898Skais ssl->activeinput = B_FALSE; 355898Skais *err = EBADMSG; 356898Skais return (1); 357898Skais } 358898Skais } 359898Skais 360898Skais static void 361898Skais kssl_update_handshake_hashes(ssl_t *ssl, uchar_t *buf, uint_t len) 362898Skais { 363898Skais MD5Update(&ssl->hs_md5, buf, len); 364898Skais SHA1Update(&ssl->hs_sha1, buf, len); 365898Skais } 366898Skais 367898Skais static int 368898Skais kssl_compute_handshake_hashes( 369898Skais ssl_t *ssl, 370898Skais SSL3Hashes *hashes, 371898Skais uint32_t sender) 372898Skais { 373898Skais MD5_CTX md5 = ssl->hs_md5; /* clone md5 context */ 374898Skais SHA1_CTX sha1 = ssl->hs_sha1; /* clone sha1 context */ 375898Skais MD5_CTX *md5ctx = &md5; 376898Skais SHA1_CTX *sha1ctx = &sha1; 377898Skais 378898Skais if (IS_TLS(ssl)) { 379898Skais uchar_t seed[MD5_HASH_LEN + SHA1_HASH_LEN]; 380898Skais char *label; 381898Skais 382898Skais /* 383898Skais * Do not take another hash step here. 384898Skais * Just complete the operation. 385898Skais */ 386898Skais MD5Final(hashes->md5, md5ctx); 387898Skais SHA1Final(hashes->sha1, sha1ctx); 388898Skais 389898Skais bcopy(hashes->md5, seed, MD5_HASH_LEN); 390898Skais bcopy(hashes->sha1, seed + MD5_HASH_LEN, SHA1_HASH_LEN); 391898Skais 392898Skais if (sender == sender_client) 393898Skais label = TLS_CLIENT_FINISHED_LABEL; 394898Skais else 395898Skais label = TLS_SERVER_FINISHED_LABEL; 396898Skais 397898Skais return (kssl_tls_PRF(ssl, 398898Skais ssl->sid.master_secret, (size_t)SSL3_MASTER_SECRET_LEN, 399898Skais (uchar_t *)label, strlen(label), 400898Skais seed, (size_t)(MD5_HASH_LEN + SHA1_HASH_LEN), 401898Skais hashes->tlshash, (size_t)TLS_FINISHED_SIZE)); 402898Skais } else { 403898Skais uchar_t s[4]; 404898Skais s[0] = (sender >> 24) & 0xff; 405898Skais s[1] = (sender >> 16) & 0xff; 406898Skais s[2] = (sender >> 8) & 0xff; 407898Skais s[3] = (sender) & 0xff; 408898Skais 409898Skais MD5Update(md5ctx, s, 4); 410898Skais MD5Update(md5ctx, ssl->sid.master_secret, 411898Skais SSL3_MASTER_SECRET_LEN); 412898Skais MD5Update(md5ctx, kssl_pad_1, SSL3_MD5_PAD_LEN); 413898Skais MD5Final(hashes->md5, md5ctx); 414898Skais 415898Skais MD5Init(md5ctx); 416898Skais MD5Update(md5ctx, ssl->sid.master_secret, 417898Skais SSL3_MASTER_SECRET_LEN); 418898Skais MD5Update(md5ctx, kssl_pad_2, SSL3_MD5_PAD_LEN); 419898Skais MD5Update(md5ctx, hashes->md5, MD5_HASH_LEN); 420898Skais MD5Final(hashes->md5, md5ctx); 421898Skais 422898Skais SHA1Update(sha1ctx, s, 4); 423898Skais SHA1Update(sha1ctx, ssl->sid.master_secret, 424898Skais SSL3_MASTER_SECRET_LEN); 425898Skais SHA1Update(sha1ctx, kssl_pad_1, SSL3_SHA1_PAD_LEN); 426898Skais SHA1Final(hashes->sha1, sha1ctx); 427898Skais 428898Skais SHA1Init(sha1ctx); 429898Skais SHA1Update(sha1ctx, ssl->sid.master_secret, 430898Skais SSL3_MASTER_SECRET_LEN); 431898Skais SHA1Update(sha1ctx, kssl_pad_2, SSL3_SHA1_PAD_LEN); 432898Skais SHA1Update(sha1ctx, hashes->sha1, SHA1_HASH_LEN); 433898Skais SHA1Final(hashes->sha1, sha1ctx); 434898Skais return (0); 435898Skais } 436898Skais } 437898Skais 438898Skais 439898Skais #define KSSL_SSL3_CH_MIN_MSGLEN (39) 440898Skais 441898Skais static int 442898Skais kssl_handle_client_hello(ssl_t *ssl, mblk_t *mp, int msglen) 443898Skais { 444898Skais uchar_t *msgend; 445898Skais int err; 446898Skais SSL3AlertDescription desc = illegal_parameter; 447898Skais uint_t sidlen; 448898Skais uint_t nsuites; 449898Skais uchar_t *suitesp; 450898Skais uint_t i, j; 451898Skais uint16_t suite; 452898Skais int ch_msglen = KSSL_SSL3_CH_MIN_MSGLEN; 453898Skais 454898Skais ASSERT(mp->b_wptr >= mp->b_rptr + msglen); 455898Skais ASSERT(ssl->msg.type == client_hello); 456898Skais ASSERT(ssl->hs_waitstate == wait_client_hello); 457898Skais ASSERT(ssl->resumed == B_FALSE); 458898Skais 459898Skais if (msglen < ch_msglen) { 460898Skais goto falert; 461898Skais } 462898Skais 463898Skais msgend = mp->b_rptr + msglen; 464898Skais 465898Skais /* Support SSLv3 (version == 3.0) or TLS (version == 3.1) */ 466898Skais if (ssl->major_version != 3 || (ssl->major_version == 3 && 467898Skais ssl->minor_version != 0 && ssl->minor_version != 1)) { 468898Skais KSSL_DEBUG3_IF(kssl_debug, 469898Skais "HandleClientHello: handshake failure - " 470898Skais "SSL version not supported (%d %d)", 471898Skais ssl->major_version, ssl->minor_version); 472898Skais desc = handshake_failure; 473898Skais goto falert; 474898Skais } 475898Skais mp->b_rptr += 2; /* skip the version bytes */ 476898Skais 477898Skais bcopy(mp->b_rptr, ssl->client_random, SSL3_RANDOM_LENGTH); 478898Skais mp->b_rptr += SSL3_RANDOM_LENGTH; 479898Skais 480898Skais ASSERT(ssl->sid.cached == B_FALSE); 481898Skais sidlen = *mp->b_rptr++; 482898Skais ch_msglen += sidlen; 483898Skais if (msglen < ch_msglen) { 484898Skais goto falert; 485898Skais } 486898Skais if (sidlen != SSL3_SESSIONID_BYTES) { 487898Skais mp->b_rptr += sidlen; 488898Skais } else { 489898Skais kssl_lookup_sid(&ssl->sid, mp->b_rptr, ssl->faddr, 490898Skais ssl->kssl_entry); 491898Skais mp->b_rptr += SSL3_SESSIONID_BYTES; 492898Skais } 493898Skais 494898Skais nsuites = ((uint_t)mp->b_rptr[0] << 8) + (uint_t)mp->b_rptr[1]; 495898Skais mp->b_rptr += 2; 496898Skais ch_msglen += nsuites; 497898Skais if (msglen != ch_msglen) { 498898Skais goto falert; 499898Skais } 500898Skais if (nsuites & 0x1) { 501898Skais goto falert; 502898Skais } 503898Skais suitesp = mp->b_rptr; 504898Skais if (ssl->sid.cached == B_TRUE) { 505898Skais suite = ssl->sid.cipher_suite; 506898Skais for (j = 0; j < nsuites; j += 2) { 507898Skais if (suitesp[j] == ((suite >> 8) & 0xff) && 508898Skais suitesp[j + 1] == (suite & 0xff)) { 509898Skais break; 510898Skais } 511898Skais } 512898Skais if (j < nsuites) { 513898Skais goto suite_found; 514898Skais } 515898Skais kssl_uncache_sid(&ssl->sid, ssl->kssl_entry); 516898Skais ssl->sid.cached = B_FALSE; 517898Skais } 518898Skais 519898Skais /* Check if this server is capable of the cipher suite */ 520898Skais for (i = 0; i < ssl->kssl_entry->kssl_cipherSuites_nentries; i++) { 521898Skais suite = ssl->kssl_entry->kssl_cipherSuites[i]; 522898Skais for (j = 0; j < nsuites; j += 2) { 523898Skais if (suitesp[j] == ((suite >> 8) & 0xff) && 524898Skais suitesp[j + 1] == (suite & 0xff)) { 525898Skais break; 526898Skais } 527898Skais } 528898Skais if (j < nsuites) { 529898Skais break; 530898Skais } 531898Skais } 532898Skais if (i == ssl->kssl_entry->kssl_cipherSuites_nentries) { 533898Skais if (ssl->sslcnt == 1) { 534898Skais KSSL_COUNTER(no_suite_found, 1); 535898Skais return (SSL_MISS); 536898Skais } 537898Skais desc = handshake_failure; 538898Skais KSSL_DEBUG1_IF(kssl_debug, 539898Skais "kssl_handle_client_hello: no cipher suites found"); 540898Skais goto falert; 541898Skais } 542898Skais 543898Skais suite_found: 544898Skais 545898Skais mp->b_rptr += nsuites; 546898Skais if (*mp->b_rptr++ != 1 || *mp->b_rptr++ != 0) { 547898Skais desc = handshake_failure; 548898Skais KSSL_DEBUG1_IF(kssl_debug, 549898Skais "kssl_handle_client_hello: handshake failure"); 550898Skais goto falert; 551898Skais } 552898Skais 553898Skais mp->b_rptr = msgend; 554898Skais 555898Skais for (i = 0; i < cipher_suite_defs_nentries; i++) { 556898Skais if (suite == cipher_suite_defs[i].suite) { 557898Skais break; 558898Skais } 559898Skais } 560898Skais 561898Skais ASSERT(i < cipher_suite_defs_nentries); 562898Skais 563898Skais ssl->pending_cipher_suite = suite; 564898Skais ssl->pending_malg = cipher_suite_defs[i].malg; 565898Skais ssl->pending_calg = cipher_suite_defs[i].calg; 566898Skais ssl->pending_keyblksz = cipher_suite_defs[i].keyblksz; 567898Skais 568898Skais if (ssl->sid.cached == B_TRUE) { 569898Skais err = kssl_send_server_hello(ssl); 570898Skais if (err != 0) { 571898Skais return (err); 572898Skais } 573898Skais if (IS_TLS(ssl)) 574898Skais err = kssl_generate_tls_keyblock(ssl); 575898Skais else 576898Skais kssl_generate_keyblock(ssl); 577898Skais 578898Skais err = kssl_send_change_cipher_specs(ssl); 579898Skais if (err != 0) { 580898Skais return (err); 581898Skais } 582898Skais 583898Skais err = kssl_send_finished(ssl, 1); 584898Skais if (err != 0) 585898Skais return (err); 586898Skais 587898Skais err = kssl_compute_handshake_hashes(ssl, &ssl->hs_hashes, 588898Skais sender_client); 589898Skais if (err != 0) 590898Skais return (err); 591898Skais 592898Skais ssl->hs_waitstate = wait_change_cipher; 593898Skais ssl->resumed = B_TRUE; 594898Skais ssl->activeinput = B_FALSE; 595898Skais KSSL_COUNTER(resumed_sessions, 1); 596898Skais return (0); 597898Skais } 598898Skais 599898Skais (void) random_get_pseudo_bytes(ssl->sid.session_id, 600898Skais SSL3_SESSIONID_BYTES); 601898Skais ssl->sid.client_addr = ssl->faddr; 602898Skais ssl->sid.cipher_suite = suite; 603898Skais 604898Skais err = kssl_send_server_hello(ssl); 605898Skais if (err != 0) { 606898Skais return (err); 607898Skais } 608898Skais err = kssl_send_certificate_and_server_hello_done(ssl); 609898Skais if (err != 0) { 610898Skais return (err); 611898Skais } 612898Skais KSSL_COUNTER(full_handshakes, 1); 613898Skais ssl->hs_waitstate = wait_client_key; 614898Skais ssl->activeinput = B_FALSE; 615898Skais return (0); 616898Skais 617898Skais falert: 618898Skais kssl_send_alert(ssl, alert_fatal, desc); 619898Skais return (EBADMSG); 620898Skais } 621898Skais 622898Skais static void 623898Skais kssl_cache_sid(sslSessionID *sid, kssl_entry_t *kssl_entry) 624898Skais { 625898Skais uint_t index; 626898Skais uchar_t *s = sid->session_id; 627898Skais int l = SSL3_SESSIONID_BYTES - 1; 628898Skais kmutex_t *lock; 629898Skais 630898Skais ASSERT(sid->cached == B_TRUE); 631898Skais 632898Skais index = (int)sid->client_addr ^ (((int)s[0] << 24) | ((int)s[1] << 16) | 633898Skais ((int)s[2] << 8) | (int)s[l]); 634898Skais 635898Skais index %= kssl_entry->sid_cache_nentries; 636898Skais 637898Skais sid->time = lbolt; 638898Skais 639898Skais lock = &(kssl_entry->sid_cache[index].se_lock); 640898Skais mutex_enter(lock); 641898Skais kssl_entry->sid_cache[index].se_used++; 642898Skais bcopy(sid, &(kssl_entry->sid_cache[index].se_sid), sizeof (*sid)); 643898Skais mutex_exit(lock); 644898Skais } 645898Skais 646898Skais static void 647898Skais kssl_lookup_sid(sslSessionID *sid, uchar_t *s, ipaddr_t faddr, 648898Skais kssl_entry_t *kssl_entry) 649898Skais { 650898Skais uint_t index; 651898Skais int l = SSL3_SESSIONID_BYTES - 1; 652898Skais kmutex_t *lock; 653898Skais sslSessionID *csid; 654898Skais 655898Skais ASSERT(sid->cached == B_FALSE); 656898Skais 657898Skais KSSL_COUNTER(sid_cache_lookups, 1); 658898Skais 659898Skais index = (int)faddr ^ (((int)s[0] << 24) | ((int)s[1] << 16) | 660898Skais ((int)s[2] << 8) | (int)s[l]); 661898Skais 662898Skais index %= kssl_entry->sid_cache_nentries; 663898Skais 664898Skais lock = &(kssl_entry->sid_cache[index].se_lock); 665898Skais mutex_enter(lock); 666898Skais csid = &(kssl_entry->sid_cache[index].se_sid); 667898Skais if (csid->cached == B_FALSE || csid->client_addr != faddr || 668898Skais bcmp(csid->session_id, s, SSL3_SESSIONID_BYTES)) { 669898Skais mutex_exit(lock); 670898Skais return; 671898Skais } 672898Skais 673898Skais if (TICK_TO_SEC(lbolt - csid->time) > kssl_entry->sid_cache_timeout) { 674898Skais csid->cached = B_FALSE; 675898Skais mutex_exit(lock); 676898Skais return; 677898Skais } 678898Skais 679898Skais bcopy(csid, sid, sizeof (*sid)); 680898Skais mutex_exit(lock); 681898Skais ASSERT(sid->cached == B_TRUE); 682898Skais 683898Skais KSSL_COUNTER(sid_cache_hits, 1); 684898Skais } 685898Skais 686898Skais static uchar_t * 687898Skais kssl_rsa_unwrap(uchar_t *buf, size_t *lenp) 688898Skais { 689898Skais size_t len = *lenp; 690898Skais int i = 2; 691898Skais 692898Skais if (buf[0] != 0 || buf[1] != 2) { 693898Skais return (NULL); 694898Skais } 695898Skais 696898Skais while (i < len) { 697898Skais if (buf[i++] == 0) { 698898Skais *lenp = len - i; 699898Skais break; 700898Skais } 701898Skais } 702898Skais 703898Skais if (i == len) { 704898Skais return (NULL); 705898Skais } 706898Skais 707898Skais return (buf + i); 708898Skais } 709898Skais 710898Skais void 711898Skais kssl_uncache_sid(sslSessionID *sid, kssl_entry_t *kssl_entry) 712898Skais { 713898Skais uint_t index; 714898Skais uchar_t *s = sid->session_id; 715898Skais int l = SSL3_SESSIONID_BYTES - 1; 716898Skais sslSessionID *csid; 717898Skais kmutex_t *lock; 718898Skais 719898Skais ASSERT(sid->cached == B_TRUE); 720898Skais 721898Skais KSSL_COUNTER(sid_uncached, 1); 722898Skais 723898Skais index = (int)sid->client_addr ^ (((int)s[0] << 24) | ((int)s[1] << 16) | 724898Skais ((int)s[2] << 8) | (int)s[l]); 725898Skais 726898Skais index %= kssl_entry->sid_cache_nentries; 727898Skais 728898Skais lock = &(kssl_entry->sid_cache[index].se_lock); 729898Skais mutex_enter(lock); 730898Skais csid = &(kssl_entry->sid_cache[index].se_sid); 731898Skais if (csid->client_addr != sid->client_addr || 732898Skais bcmp(csid->session_id, s, SSL3_SESSIONID_BYTES)) { 733898Skais mutex_exit(lock); 734898Skais return; 735898Skais } 736898Skais csid->cached = B_FALSE; 737898Skais mutex_exit(lock); 738898Skais } 739898Skais 740898Skais 741898Skais #define KSSL_SSL3_SH_RECLEN (74) 742898Skais #define KSSL_SSL3_FIN_MSGLEN (36) 743898Skais 744898Skais #define KSSL_SSL3_MAX_CCP_FIN_MSGLEN (128) /* comfortable upper bound */ 745898Skais 746898Skais static int 747898Skais kssl_send_server_hello(ssl_t *ssl) 748898Skais { 749898Skais mblk_t *mp; 750898Skais uchar_t *buf; 751898Skais uchar_t *msgstart; 752898Skais 753898Skais mp = allocb(ssl->tcp_mss, BPRI_HI); 754898Skais if (mp == NULL) { 755898Skais KSSL_COUNTER(alloc_fails, 1); 756898Skais return (ENOMEM); 757898Skais } 758898Skais ssl->handshake_sendbuf = mp; 759898Skais buf = mp->b_wptr; 760898Skais 761898Skais /* 5 byte record header */ 762898Skais buf[0] = content_handshake; 763898Skais buf[1] = ssl->major_version; 764898Skais buf[2] = ssl->minor_version; 765898Skais buf[3] = KSSL_SSL3_SH_RECLEN >> 8; 766898Skais buf[4] = KSSL_SSL3_SH_RECLEN & 0xff; 767898Skais buf += SSL3_HDR_LEN; 768898Skais 769898Skais msgstart = buf; 770898Skais 771898Skais /* 6 byte message header */ 772898Skais buf[0] = (uchar_t)server_hello; /* message type */ 773898Skais buf[1] = 0; /* message len byte 0 */ 774898Skais buf[2] = ((KSSL_SSL3_SH_RECLEN - 4) >> 8) & 775898Skais 0xff; /* message len byte 1 */ 776898Skais buf[3] = (KSSL_SSL3_SH_RECLEN - 4) & 0xff; /* message len byte 2 */ 777898Skais 778898Skais buf[4] = ssl->major_version; /* version byte 0 */ 779898Skais buf[5] = ssl->minor_version; /* version byte 1 */ 780898Skais 781898Skais buf += 6; 782898Skais 783898Skais kssl_get_hello_random(ssl->server_random); 784898Skais bcopy(ssl->server_random, buf, SSL3_RANDOM_LENGTH); 785898Skais buf += SSL3_RANDOM_LENGTH; 786898Skais 787898Skais buf[0] = SSL3_SESSIONID_BYTES; 788898Skais bcopy(ssl->sid.session_id, buf + 1, SSL3_SESSIONID_BYTES); 789898Skais buf += SSL3_SESSIONID_BYTES + 1; 790898Skais 791898Skais buf[0] = (ssl->pending_cipher_suite >> 8) & 0xff; 792898Skais buf[1] = ssl->pending_cipher_suite & 0xff; 793898Skais 794898Skais buf[2] = 0; /* No compression */ 795898Skais 796898Skais mp->b_wptr = buf + 3; 797898Skais ASSERT(mp->b_wptr < mp->b_datap->db_lim); 798898Skais 799898Skais kssl_update_handshake_hashes(ssl, msgstart, KSSL_SSL3_SH_RECLEN); 800898Skais return (0); 801898Skais } 802898Skais 803898Skais static void 804898Skais kssl_get_hello_random(uchar_t *buf) 805898Skais { 806898Skais timestruc_t ts; 807898Skais time_t sec; 808898Skais 809898Skais gethrestime(&ts); 810898Skais sec = ts.tv_sec; 811898Skais 812898Skais buf[0] = (sec >> 24) & 0xff; 813898Skais buf[1] = (sec >> 16) & 0xff; 814898Skais buf[2] = (sec >> 8) & 0xff; 815898Skais buf[3] = (sec) & 0xff; 816898Skais 817898Skais (void) random_get_pseudo_bytes(&buf[4], SSL3_RANDOM_LENGTH - 4); 818898Skais 819898Skais /* Should this be caching? */ 820898Skais } 821898Skais 822898Skais static int 823898Skais kssl_tls_P_hash(crypto_mechanism_t *mech, crypto_key_t *key, 824898Skais size_t hashlen, 825898Skais uchar_t *label, size_t label_len, 826898Skais uchar_t *seed, size_t seedlen, 827898Skais uchar_t *data, size_t datalen) 828898Skais { 829898Skais int rv = 0; 830898Skais uchar_t A1[MAX_HASH_LEN], result[MAX_HASH_LEN]; 831898Skais int bytes_left = datalen; 832898Skais crypto_data_t dd, mac; 833898Skais crypto_context_t ctx; 834898Skais 835898Skais dd.cd_format = CRYPTO_DATA_RAW; 836898Skais dd.cd_offset = 0; 837898Skais mac.cd_format = CRYPTO_DATA_RAW; 838898Skais mac.cd_offset = 0; 839898Skais 840898Skais /* 841898Skais * A(i) = HMAC_hash(secred, seed + A(i-1)); 842898Skais * A(0) = seed; 843898Skais * 844898Skais * Compute A(1): 845898Skais * A(1) = HMAC_hash(secret, label + seed) 846898Skais * 847898Skais */ 848898Skais HMAC_INIT(mech, key, &ctx); 849898Skais HMAC_UPDATE(ctx, label, label_len); 850898Skais HMAC_UPDATE(ctx, seed, seedlen); 851898Skais HMAC_FINAL(ctx, A1, hashlen); 852898Skais 853898Skais /* Compute A(2) ... A(n) */ 854898Skais while (bytes_left > 0) { 855898Skais HMAC_INIT(mech, key, &ctx); 856898Skais HMAC_UPDATE(ctx, A1, hashlen); 857898Skais HMAC_UPDATE(ctx, label, label_len); 858898Skais HMAC_UPDATE(ctx, seed, seedlen); 859898Skais HMAC_FINAL(ctx, result, hashlen); 860898Skais 861898Skais /* 862898Skais * The A(i) value is stored in "result". 863898Skais * Save the results of the MAC so it can be input to next 864898Skais * iteration. 865898Skais */ 866898Skais if (bytes_left > hashlen) { 867898Skais /* Store the chunk result */ 868898Skais bcopy(result, data, hashlen); 869898Skais data += hashlen; 870898Skais 871898Skais bytes_left -= hashlen; 872898Skais 873898Skais /* Update A1 for next iteration */ 874898Skais HMAC_INIT(mech, key, &ctx); 875898Skais HMAC_UPDATE(ctx, A1, hashlen); 876898Skais HMAC_FINAL(ctx, A1, hashlen); 877898Skais 878898Skais } else { 879898Skais bcopy(result, data, bytes_left); 880898Skais data += bytes_left; 881898Skais bytes_left = 0; 882898Skais } 883898Skais } 884898Skais end: 885898Skais if (CRYPTO_ERR(rv)) { 886898Skais #ifdef DEBUG 887898Skais cmn_err(CE_WARN, "kssl_P_hash: crypto_mac error 0x%02X", rv); 888898Skais #endif /* DEBUG */ 889898Skais KSSL_COUNTER(compute_mac_failure, 1); 890898Skais } 891898Skais return (rv); 892898Skais } 893898Skais 894898Skais /* ARGSUSED */ 895898Skais static int 896898Skais kssl_tls_PRF(ssl_t *ssl, 897898Skais uchar_t *secret, size_t secret_len, 898898Skais uchar_t *label, size_t label_len, 899898Skais uchar_t *seed, size_t seed_len, 900898Skais uchar_t *prfresult, size_t prfresult_len) 901898Skais { 902898Skais /* 903898Skais * RFC 2246: 904898Skais * PRF(secret, label, seed) = P_MD5(S1, label + seed) XOR 905898Skais * P_SHA1(S2, label + seed); 906898Skais * S1 = 1st half of secret. 907898Skais * S1 = 2nd half of secret. 908898Skais * 909898Skais */ 910898Skais 911898Skais int rv = 0, i; 912898Skais uchar_t psha1[MAX_TLS_KEYBLOCK_SIZE]; 913898Skais crypto_key_t S1, S2; 914898Skais 915898Skais /* length of secret keys is ceil(length/2) */ 916898Skais size_t slen = roundup(secret_len, 2) / 2; 917898Skais 918898Skais if (prfresult_len > MAX_TLS_KEYBLOCK_SIZE) { 919898Skais KSSL_DEBUG2_IF(kssl_debug, "kssl_tls_PRF: unexpected keyblock " 920898Skais "size (%lu)", prfresult_len); 921898Skais return (CRYPTO_ARGUMENTS_BAD); 922898Skais } 923898Skais 924898Skais ASSERT(prfresult != NULL); 925898Skais ASSERT(label != NULL); 926898Skais ASSERT(seed != NULL); 927898Skais 928898Skais S1.ck_data = secret; 929898Skais S1.ck_length = slen * 8; /* bits */ 930898Skais S1.ck_format = CRYPTO_KEY_RAW; 931898Skais 932898Skais S2.ck_data = secret + slen; 933898Skais S2.ck_length = slen * 8; /* bits */ 934898Skais S2.ck_format = CRYPTO_KEY_RAW; 935898Skais 936898Skais rv = kssl_tls_P_hash(&hmac_md5_mech, &S1, MD5_HASH_LEN, 937898Skais label, label_len, 938898Skais seed, seed_len, 939898Skais prfresult, prfresult_len); 940898Skais if (CRYPTO_ERR(rv)) 941898Skais goto end; 942898Skais 943898Skais rv = kssl_tls_P_hash(&hmac_sha1_mech, &S2, SHA1_HASH_LEN, 944898Skais label, label_len, 945898Skais seed, seed_len, 946898Skais psha1, prfresult_len); 947898Skais if (CRYPTO_ERR(rv)) 948898Skais goto end; 949898Skais 950898Skais for (i = 0; i < prfresult_len; i++) 951898Skais prfresult[i] ^= psha1[i]; 952898Skais 953898Skais end: 954898Skais if (CRYPTO_ERR(rv)) 955898Skais bzero(prfresult, prfresult_len); 956898Skais 957898Skais return (rv); 958898Skais } 959898Skais 9601724Skrishna #define IS_BAD_PRE_MASTER_SECRET(pms, pmslen, ssl) \ 9611724Skrishna (pms == NULL || pmslen != SSL3_PRE_MASTER_SECRET_LEN || \ 9621724Skrishna pms[0] != ssl->major_version || pms[1] != ssl->minor_version) 9631724Skrishna 9641724Skrishna #define FAKE_PRE_MASTER_SECRET(pms, pmslen, ssl, buf) { \ 9651724Skrishna KSSL_COUNTER(bad_pre_master_secret, 1); \ 9661724Skrishna pms = buf; \ 9671724Skrishna pmslen = SSL3_PRE_MASTER_SECRET_LEN; \ 9681724Skrishna pms[0] = ssl->major_version; \ 9691724Skrishna pms[1] = ssl->minor_version; \ 9701724Skrishna (void) random_get_pseudo_bytes(&buf[2], pmslen - 2); \ 9711724Skrishna } 9721724Skrishna 973898Skais static int 974898Skais kssl_generate_tls_ms(ssl_t *ssl, uchar_t *pms, size_t pmslen) 975898Skais { 9761724Skrishna uchar_t buf[SSL3_PRE_MASTER_SECRET_LEN]; 977898Skais uchar_t seed[SSL3_RANDOM_LENGTH * 2]; 978898Skais 979898Skais /* 980898Skais * Computing the master secret: 981898Skais * ---------------------------- 982898Skais * master_secret = PRF (pms, "master secret", 983898Skais * ClientHello.random + ServerHello.random); 984898Skais */ 985898Skais bcopy(ssl->client_random, seed, SSL3_RANDOM_LENGTH); 986898Skais bcopy(ssl->server_random, seed + SSL3_RANDOM_LENGTH, 987898Skais SSL3_RANDOM_LENGTH); 988898Skais 9891724Skrishna /* if pms is bad fake it to thwart Bleichenbacher attack */ 9901724Skrishna if (IS_BAD_PRE_MASTER_SECRET(pms, pmslen, ssl)) { 9911724Skrishna #ifdef DEBUG 9921724Skrishna cmn_err(CE_WARN, "Under Bleichenbacher attack"); 9931724Skrishna #endif /* DEBUG */ 9941724Skrishna FAKE_PRE_MASTER_SECRET(pms, pmslen, ssl, buf); 9951724Skrishna } 9961724Skrishna 997898Skais return (kssl_tls_PRF(ssl, 998898Skais pms, pmslen, 999898Skais (uchar_t *)TLS_MASTER_SECRET_LABEL, 1000898Skais (size_t)strlen(TLS_MASTER_SECRET_LABEL), 1001898Skais seed, sizeof (seed), 1002898Skais ssl->sid.master_secret, 1003898Skais (size_t)sizeof (ssl->sid.master_secret))); 1004898Skais } 1005898Skais 10061724Skrishna 1007898Skais static void 1008898Skais kssl_generate_ssl_ms(ssl_t *ssl, uchar_t *pms, size_t pmslen) 1009898Skais { 1010898Skais uchar_t buf[SSL3_PRE_MASTER_SECRET_LEN]; 1011898Skais uchar_t *ms; 1012898Skais int hlen = MD5_HASH_LEN; 1013898Skais 1014898Skais ms = ssl->sid.master_secret; 1015898Skais 1016898Skais /* if pms is bad fake it to thwart Bleichenbacher attack */ 10171724Skrishna if (IS_BAD_PRE_MASTER_SECRET(pms, pmslen, ssl)) { 1018898Skais #ifdef DEBUG 1019898Skais cmn_err(CE_WARN, "Under Bleichenbacher attack"); 1020898Skais #endif /* DEBUG */ 10211724Skrishna FAKE_PRE_MASTER_SECRET(pms, pmslen, ssl, buf); 1022898Skais } 10231724Skrishna 1024898Skais kssl_ssl3_key_material_derive_step(ssl, pms, pmslen, 1, ms, 0); 1025898Skais kssl_ssl3_key_material_derive_step(ssl, pms, pmslen, 2, ms + hlen, 0); 1026898Skais kssl_ssl3_key_material_derive_step(ssl, pms, pmslen, 3, ms + 2 * hlen, 1027898Skais 0); 1028898Skais } 1029898Skais 1030898Skais static int 1031898Skais kssl_generate_tls_keyblock(ssl_t *ssl) 1032898Skais { 1033898Skais uchar_t seed[2 * SSL3_RANDOM_LENGTH]; 1034898Skais 1035898Skais bcopy(ssl->server_random, seed, SSL3_RANDOM_LENGTH); 1036898Skais bcopy(ssl->client_random, seed + SSL3_RANDOM_LENGTH, 1037898Skais SSL3_RANDOM_LENGTH); 1038898Skais 1039898Skais return (kssl_tls_PRF(ssl, ssl->sid.master_secret, 1040898Skais (size_t)SSL3_MASTER_SECRET_LEN, 1041898Skais (uchar_t *)TLS_KEY_EXPANSION_LABEL, 1042898Skais (size_t)strlen(TLS_KEY_EXPANSION_LABEL), 1043898Skais seed, (size_t)sizeof (seed), 1044898Skais ssl->pending_keyblock, 1045898Skais (size_t)ssl->pending_keyblksz)); 1046898Skais 1047898Skais } 1048898Skais 1049898Skais static void 1050898Skais kssl_generate_keyblock(ssl_t *ssl) 1051898Skais { 1052898Skais uchar_t *ms; 1053898Skais size_t mslen = SSL3_MASTER_SECRET_LEN; 1054898Skais int hlen = MD5_HASH_LEN; 1055898Skais uchar_t *keys = ssl->pending_keyblock; 1056898Skais int steps = howmany(ssl->pending_keyblksz, hlen); 1057898Skais int i; 1058898Skais 1059898Skais ms = ssl->sid.master_secret; 1060898Skais 1061898Skais ASSERT(hlen * steps <= MAX_KEYBLOCK_LENGTH); 1062898Skais 1063898Skais for (i = 1; i <= steps; i++) { 1064898Skais kssl_ssl3_key_material_derive_step(ssl, ms, mslen, i, keys, 1); 1065898Skais keys += hlen; 1066898Skais } 1067898Skais } 1068898Skais 1069898Skais static char *ssl3_key_derive_seeds[8] = {"A", "BB", "CCC", "DDDD", "EEEEE", 1070898Skais "FFFFFF", "GGGGGGG", "HHHHHHHH"}; 1071898Skais 1072898Skais static void 1073898Skais kssl_ssl3_key_material_derive_step( 1074898Skais ssl_t *ssl, 1075898Skais uchar_t *secret, 1076898Skais size_t secretlen, 1077898Skais int step, 1078898Skais uchar_t *dst, 1079898Skais int sr_first) 1080898Skais { 1081898Skais SHA1_CTX sha1, *sha1ctx; 1082898Skais MD5_CTX md5, *md5ctx; 1083898Skais uchar_t sha1_hash[SHA1_HASH_LEN]; 1084898Skais 1085898Skais sha1ctx = &sha1; 1086898Skais md5ctx = &md5; 1087898Skais 1088898Skais ASSERT(step <= 1089898Skais sizeof (ssl3_key_derive_seeds) / 1090898Skais sizeof (ssl3_key_derive_seeds[0])); 1091898Skais step--; 1092898Skais 1093898Skais SHA1Init(sha1ctx); 1094898Skais SHA1Update(sha1ctx, (uchar_t *)ssl3_key_derive_seeds[step], 1095898Skais step + 1); 1096898Skais SHA1Update(sha1ctx, secret, secretlen); 1097898Skais if (sr_first) { 1098898Skais SHA1Update(sha1ctx, ssl->server_random, SSL3_RANDOM_LENGTH); 1099898Skais SHA1Update(sha1ctx, ssl->client_random, SSL3_RANDOM_LENGTH); 1100898Skais } else { 1101898Skais SHA1Update(sha1ctx, ssl->client_random, SSL3_RANDOM_LENGTH); 1102898Skais SHA1Update(sha1ctx, ssl->server_random, SSL3_RANDOM_LENGTH); 1103898Skais } 1104898Skais SHA1Final(sha1_hash, sha1ctx); 1105898Skais 1106898Skais MD5Init(md5ctx); 1107898Skais MD5Update(md5ctx, secret, secretlen); 1108898Skais MD5Update(md5ctx, sha1_hash, SHA1_HASH_LEN); 1109898Skais MD5Final(dst, md5ctx); 1110898Skais } 1111898Skais 1112898Skais static int 1113898Skais kssl_send_certificate_and_server_hello_done(ssl_t *ssl) 1114898Skais { 1115898Skais int cur_reclen; 1116898Skais int mss; 1117898Skais int len, copylen; 1118898Skais mblk_t *mp; 1119898Skais uchar_t *cert_buf; 1120898Skais int cert_len; 1121898Skais uchar_t *msgbuf; 1122898Skais Certificate_t *cert; 1123898Skais 1124898Skais cert = ssl->kssl_entry->ke_server_certificate; 1125898Skais if (cert == NULL) { 1126898Skais return (ENOENT); 1127898Skais } 1128898Skais cert_buf = cert->msg; 1129898Skais cert_len = cert->len; 1130898Skais 1131898Skais mp = ssl->handshake_sendbuf; 1132898Skais mss = ssl->tcp_mss; 1133898Skais ASSERT(mp != NULL); 1134898Skais cur_reclen = mp->b_wptr - mp->b_rptr - SSL3_HDR_LEN; 1135898Skais ASSERT(cur_reclen == KSSL_SSL3_SH_RECLEN); 1136898Skais /* Assume MSS is at least 80 bytes */ 1137898Skais ASSERT(mss > cur_reclen + SSL3_HDR_LEN); 1138898Skais ASSERT(cur_reclen < SSL3_MAX_RECORD_LENGTH); /* XXX */ 1139898Skais 1140898Skais copylen = mss - (cur_reclen + SSL3_HDR_LEN); 1141898Skais len = cert_len; 1142898Skais copylen = MIN(copylen, len); 1143898Skais copylen = MIN(copylen, SSL3_MAX_RECORD_LENGTH - cur_reclen); 1144898Skais 1145898Skais /* new record always starts in a new mblk for simplicity */ 1146898Skais msgbuf = cert_buf; 1147898Skais for (;;) { 1148898Skais ASSERT(mp->b_wptr + copylen <= mp->b_datap->db_lim); 1149898Skais bcopy(msgbuf, mp->b_wptr, copylen); 1150898Skais msgbuf += copylen; 1151898Skais mp->b_wptr += copylen; 1152898Skais cur_reclen += copylen; 1153898Skais len -= copylen; 1154898Skais if (len == 0) { 1155898Skais break; 1156898Skais } 1157898Skais if (cur_reclen == SSL3_MAX_RECORD_LENGTH) { 1158898Skais cur_reclen = 0; 1159898Skais } 1160898Skais copylen = MIN(len, mss); 1161898Skais copylen = MIN(copylen, SSL3_MAX_RECORD_LENGTH - cur_reclen); 1162898Skais mp->b_cont = allocb(copylen, BPRI_HI); 1163898Skais if (mp->b_cont == NULL) { 1164898Skais KSSL_COUNTER(alloc_fails, 1); 1165898Skais freemsg(ssl->handshake_sendbuf); 1166898Skais ssl->handshake_sendbuf = NULL; 1167898Skais return (ENOMEM); 1168898Skais } 1169898Skais mp = mp->b_cont; 1170898Skais if (cur_reclen == 0) { 1171898Skais mp->b_wptr[0] = content_handshake; 1172898Skais mp->b_wptr[1] = ssl->major_version; 1173898Skais mp->b_wptr[2] = ssl->minor_version; 1174898Skais cur_reclen = MIN(len, SSL3_MAX_RECORD_LENGTH); 1175898Skais mp->b_wptr[3] = (cur_reclen >> 8) & 0xff; 1176898Skais mp->b_wptr[4] = (cur_reclen) & 0xff; 1177898Skais mp->b_wptr += SSL3_HDR_LEN; 1178898Skais cur_reclen = 0; 1179898Skais copylen = MIN(copylen, mss - SSL3_HDR_LEN); 1180898Skais } 1181898Skais } 1182898Skais 1183898Skais /* adjust the record length field for the first record */ 1184898Skais mp = ssl->handshake_sendbuf; 1185898Skais cur_reclen = MIN(KSSL_SSL3_SH_RECLEN + cert_len, 1186898Skais SSL3_MAX_RECORD_LENGTH); 1187898Skais mp->b_rptr[3] = (cur_reclen >> 8) & 0xff; 1188898Skais mp->b_rptr[4] = (cur_reclen) & 0xff; 1189898Skais 1190898Skais kssl_update_handshake_hashes(ssl, cert_buf, cert_len); 1191898Skais 1192898Skais return (0); 1193898Skais } 1194898Skais 1195898Skais static int 1196898Skais kssl_send_change_cipher_specs(ssl_t *ssl) 1197898Skais { 1198898Skais mblk_t *mp, *newmp; 1199898Skais uchar_t *buf; 1200898Skais 1201898Skais mp = ssl->handshake_sendbuf; 1202898Skais 1203898Skais /* We're most likely to hit the fast path for resumed sessions */ 1204898Skais if ((mp != NULL) && 1205898Skais (mp->b_datap->db_lim - mp->b_wptr > KSSL_SSL3_MAX_CCP_FIN_MSGLEN)) { 1206898Skais buf = mp->b_wptr; 1207898Skais } else { 1208898Skais newmp = allocb(KSSL_SSL3_MAX_CCP_FIN_MSGLEN, BPRI_HI); 1209898Skais 1210898Skais if (newmp == NULL) 1211898Skais return (ENOMEM); /* need to do better job! */ 1212898Skais 1213898Skais if (mp == NULL) { 1214898Skais ssl->handshake_sendbuf = newmp; 1215898Skais } else { 1216898Skais linkb(ssl->handshake_sendbuf, newmp); 1217898Skais } 1218898Skais mp = newmp; 1219898Skais buf = mp->b_rptr; 1220898Skais } 1221898Skais 1222898Skais /* 5 byte record header */ 1223898Skais buf[0] = content_change_cipher_spec; 1224898Skais buf[1] = ssl->major_version; 1225898Skais buf[2] = ssl->minor_version; 1226898Skais buf[3] = 0; 1227898Skais buf[4] = 1; 1228898Skais buf += SSL3_HDR_LEN; 1229898Skais 1230898Skais buf[0] = 1; 1231898Skais 1232898Skais mp->b_wptr = buf + 1; 1233898Skais ASSERT(mp->b_wptr < mp->b_datap->db_lim); 1234898Skais 1235898Skais ssl->seq_num[KSSL_WRITE] = 0; 1236898Skais return (kssl_spec_init(ssl, KSSL_WRITE)); 1237898Skais } 1238898Skais 1239898Skais int 1240898Skais kssl_spec_init(ssl_t *ssl, int dir) 1241898Skais { 1242898Skais KSSL_HASHCTX *ctx; 1243898Skais KSSLCipherSpec *spec = &ssl->spec[dir]; 1244898Skais int ret = 0; 1245898Skais 1246898Skais spec->mac_hashsz = mac_defs[ssl->pending_malg].hashsz; 1247898Skais spec->mac_padsz = mac_defs[ssl->pending_malg].padsz; 1248898Skais 1249898Skais spec->MAC_HashInit = mac_defs[ssl->pending_malg].HashInit; 1250898Skais spec->MAC_HashUpdate = mac_defs[ssl->pending_malg].HashUpdate; 1251898Skais spec->MAC_HashFinal = mac_defs[ssl->pending_malg].HashFinal; 1252898Skais 1253898Skais if (dir == KSSL_READ) { 1254898Skais bcopy(ssl->pending_keyblock, ssl->mac_secret[dir], 1255898Skais spec->mac_hashsz); 1256898Skais } else { 1257898Skais bcopy(&(ssl->pending_keyblock[spec->mac_hashsz]), 1258898Skais ssl->mac_secret[dir], spec->mac_hashsz); 1259898Skais } 1260898Skais 1261898Skais /* Pre-compute these here. will save cycles on each record later */ 1262898Skais if (!IS_TLS(ssl)) { 1263898Skais ctx = &ssl->mac_ctx[dir][0]; 1264898Skais spec->MAC_HashInit((void *)ctx); 1265898Skais spec->MAC_HashUpdate((void *)ctx, ssl->mac_secret[dir], 1266898Skais spec->mac_hashsz); 1267898Skais spec->MAC_HashUpdate((void *)ctx, kssl_pad_1, 1268898Skais spec->mac_padsz); 1269898Skais 1270898Skais ctx = &ssl->mac_ctx[dir][1]; 1271898Skais spec->MAC_HashInit((void *)ctx); 1272898Skais spec->MAC_HashUpdate((void *)ctx, ssl->mac_secret[dir], 1273898Skais spec->mac_hashsz); 1274898Skais spec->MAC_HashUpdate((void *)ctx, kssl_pad_2, 1275898Skais spec->mac_padsz); 1276898Skais } 1277898Skais 1278898Skais spec->cipher_type = cipher_defs[ssl->pending_calg].type; 1279898Skais spec->cipher_mech.cm_type = cipher_defs[ssl->pending_calg].mech_type; 1280898Skais spec->cipher_bsize = cipher_defs[ssl->pending_calg].bsize; 1281898Skais spec->cipher_keysz = cipher_defs[ssl->pending_calg].keysz; 1282898Skais 1283898Skais if (spec->cipher_ctx != NULL) { 1284898Skais crypto_cancel_ctx(spec->cipher_ctx); 1285898Skais spec->cipher_ctx = 0; 1286898Skais } 1287898Skais 1288898Skais /* 1289*4859Skrishna * Initialize HMAC keys for TLS and SSL3 HMAC keys 1290*4859Skrishna * for SSL 3.0. 1291898Skais */ 1292898Skais if (IS_TLS(ssl)) { 1293898Skais if (ssl->pending_malg == mac_md5) { 1294898Skais spec->hmac_mech = hmac_md5_mech; 1295898Skais } else if (ssl->pending_malg == mac_sha) { 1296898Skais spec->hmac_mech = hmac_sha1_mech; 1297898Skais } 1298898Skais 1299898Skais spec->hmac_key.ck_format = CRYPTO_KEY_RAW; 1300898Skais spec->hmac_key.ck_data = ssl->mac_secret[dir]; 1301898Skais spec->hmac_key.ck_length = spec->mac_hashsz * 8; 1302*4859Skrishna } else { 1303*4859Skrishna static uint32_t param; 1304*4859Skrishna 1305*4859Skrishna spec->hmac_mech.cm_type = CRYPTO_MECH_INVALID; 1306*4859Skrishna spec->hmac_mech.cm_param = (caddr_t)¶m; 1307*4859Skrishna spec->hmac_mech.cm_param_len = sizeof (param); 1308*4859Skrishna if (ssl->pending_malg == mac_md5) { 1309*4859Skrishna spec->hmac_mech.cm_type = 1310*4859Skrishna crypto_mech2id("CKM_SSL3_MD5_MAC"); 1311*4859Skrishna param = MD5_HASH_LEN; 1312*4859Skrishna } else if (ssl->pending_malg == mac_sha) { 1313*4859Skrishna spec->hmac_mech.cm_type = 1314*4859Skrishna crypto_mech2id("CKM_SSL3_SHA1_MAC"); 1315*4859Skrishna param = SHA1_HASH_LEN; 1316*4859Skrishna } 1317*4859Skrishna 1318*4859Skrishna spec->hmac_key.ck_format = CRYPTO_KEY_RAW; 1319*4859Skrishna spec->hmac_key.ck_data = ssl->mac_secret[dir]; 1320*4859Skrishna spec->hmac_key.ck_length = spec->mac_hashsz * 8; 1321898Skais } 1322898Skais 1323898Skais /* We're done if this is the nil cipher */ 1324898Skais if (spec->cipher_keysz == 0) { 1325898Skais return (0); 1326898Skais } 1327898Skais 1328898Skais /* Initialize the key and the active context */ 1329898Skais spec->cipher_key.ck_format = CRYPTO_KEY_RAW; 1330898Skais spec->cipher_key.ck_length = 8 * spec->cipher_keysz; /* in bits */ 1331898Skais 1332898Skais if (cipher_defs[ssl->pending_calg].bsize > 0) { 1333898Skais /* client_write_IV */ 1334898Skais spec->cipher_mech.cm_param = 1335898Skais (caddr_t)&(ssl->pending_keyblock[2 * spec->mac_hashsz + 1336898Skais 2 * spec->cipher_keysz]); 1337898Skais spec->cipher_mech.cm_param_len = spec->cipher_bsize; 1338898Skais } 1339898Skais spec->cipher_data.cd_format = CRYPTO_DATA_RAW; 1340898Skais if (dir == KSSL_READ) { 1341898Skais spec->cipher_mech.cm_param_len = 1342898Skais cipher_defs[ssl->pending_calg].bsize; 1343898Skais 13442800Skrishna /* client_write_key */ 1345898Skais spec->cipher_key.ck_data = 1346898Skais &(ssl->pending_keyblock[2 * spec->mac_hashsz]); 1347898Skais 1348898Skais ret = crypto_decrypt_init(&(spec->cipher_mech), 1349898Skais &(spec->cipher_key), NULL, &spec->cipher_ctx, NULL); 1350898Skais #ifdef DEBUG 1351898Skais if (CRYPTO_ERR(ret)) { 1352898Skais cmn_err(CE_WARN, "kssl_spec_init: " 1353898Skais "crypto_decrypt_init error 0x%02X", ret); 1354898Skais } 1355898Skais #endif /* DEBUG */ 1356898Skais } else { 1357898Skais if (cipher_defs[ssl->pending_calg].bsize > 0) { 1358898Skais spec->cipher_mech.cm_param += spec->cipher_bsize; 1359898Skais } 1360898Skais /* server_write_key */ 1361898Skais spec->cipher_key.ck_data = 1362898Skais &(ssl->pending_keyblock[2 * spec->mac_hashsz + 1363898Skais spec->cipher_keysz]); 1364898Skais 1365898Skais ret = crypto_encrypt_init(&(spec->cipher_mech), 1366898Skais &(spec->cipher_key), NULL, &spec->cipher_ctx, NULL); 1367898Skais #ifdef DEBUG 1368898Skais if (CRYPTO_ERR(ret)) 1369898Skais cmn_err(CE_WARN, "kssl_spec_init: " 1370898Skais "crypto_encrypt_init error 0x%02X", ret); 1371898Skais #endif /* DEBUG */ 1372898Skais } 1373898Skais return (ret); 1374898Skais } 1375898Skais 1376898Skais static int 1377898Skais kssl_send_finished(ssl_t *ssl, int update_hsh) 1378898Skais { 1379898Skais mblk_t *mp; 1380898Skais uchar_t *buf; 1381898Skais uchar_t *rstart; 1382898Skais uchar_t *versionp; 1383898Skais SSL3Hashes ssl3hashes; 1384898Skais size_t finish_len; 1385898Skais int ret = 0; 1386898Skais 1387898Skais mp = ssl->handshake_sendbuf; 1388898Skais ASSERT(mp != NULL); 1389898Skais buf = mp->b_wptr; 1390898Skais ASSERT(buf - mp->b_rptr == SSL3_HDR_LEN + KSSL_SSL3_SH_RECLEN + 1391898Skais SSL3_HDR_LEN + 1 || buf - mp->b_rptr == SSL3_HDR_LEN + 1); 1392898Skais 1393898Skais rstart = buf; 1394898Skais 1395898Skais if (IS_TLS(ssl)) 1396898Skais finish_len = TLS_FINISHED_SIZE; 1397898Skais else 1398898Skais finish_len = KSSL_SSL3_FIN_MSGLEN; 1399898Skais 1400898Skais /* 5 byte record header */ 1401898Skais buf[0] = content_handshake; 1402898Skais buf[1] = ssl->major_version; 1403898Skais buf[2] = ssl->minor_version; 1404898Skais buf[3] = 0; 1405898Skais buf[4] = 4 + finish_len; 1406898Skais 1407898Skais versionp = &buf[1]; 1408898Skais 1409898Skais buf += SSL3_HDR_LEN; 1410898Skais 1411898Skais /* 4 byte message header */ 1412898Skais buf[0] = (uchar_t)finished; /* message type */ 1413898Skais buf[1] = 0; /* message len byte 0 */ 1414898Skais buf[2] = 0; /* message len byte 1 */ 1415898Skais buf[3] = finish_len; /* message len byte 2 */ 1416898Skais buf += 4; 1417898Skais 1418898Skais if (IS_TLS(ssl)) { 1419898Skais bcopy(ssl->hs_hashes.md5, ssl3hashes.md5, 1420898Skais sizeof (ssl3hashes.md5)); 1421898Skais bcopy(ssl->hs_hashes.sha1, ssl3hashes.sha1, 1422898Skais sizeof (ssl3hashes.sha1)); 1423898Skais } 1424898Skais 1425898Skais /* Compute hashes for the SENDER side */ 1426898Skais ret = kssl_compute_handshake_hashes(ssl, &ssl3hashes, sender_server); 1427898Skais if (ret != 0) 1428898Skais return (ret); 1429898Skais 1430898Skais if (IS_TLS(ssl)) { 1431898Skais bcopy(ssl3hashes.tlshash, buf, sizeof (ssl3hashes.tlshash)); 1432898Skais } else { 1433898Skais bcopy(ssl3hashes.md5, buf, MD5_HASH_LEN); 1434898Skais bcopy(ssl3hashes.sha1, buf + MD5_HASH_LEN, SHA1_HASH_LEN); 1435898Skais } 1436898Skais 1437898Skais if (update_hsh) { 1438898Skais kssl_update_handshake_hashes(ssl, buf - 4, finish_len + 4); 1439898Skais } 1440898Skais 1441898Skais mp->b_wptr = buf + finish_len; 1442898Skais 1443898Skais ret = kssl_mac_encrypt_record(ssl, content_handshake, versionp, 1444898Skais rstart, mp); 1445898Skais ASSERT(mp->b_wptr <= mp->b_datap->db_lim); 1446898Skais 1447898Skais return (ret); 1448898Skais } 1449898Skais 1450898Skais int 1451898Skais kssl_mac_encrypt_record(ssl_t *ssl, 1452898Skais SSL3ContentType ct, 1453898Skais uchar_t *versionp, 1454898Skais uchar_t *rstart, 1455898Skais mblk_t *mp) 1456898Skais { 1457898Skais KSSLCipherSpec *spec; 1458898Skais int mac_sz; 1459898Skais int ret = 0; 1460898Skais uint16_t rec_sz; 1461898Skais int pad_sz; 1462898Skais int i; 1463898Skais 1464898Skais ASSERT(ssl != NULL); 1465898Skais ASSERT(rstart >= mp->b_rptr); 1466898Skais ASSERT(rstart < mp->b_wptr); 1467898Skais 1468898Skais spec = &ssl->spec[KSSL_WRITE]; 1469898Skais mac_sz = spec->mac_hashsz; 1470898Skais 1471898Skais rec_sz = (mp->b_wptr - rstart) - SSL3_HDR_LEN; 1472898Skais ASSERT(rec_sz > 0); 1473898Skais 1474898Skais if (mac_sz != 0) { 1475898Skais ASSERT(mp->b_wptr + mac_sz <= mp->b_datap->db_lim); 1476898Skais ret = kssl_compute_record_mac(ssl, KSSL_WRITE, 1477898Skais ssl->seq_num[KSSL_WRITE], ct, versionp, 1478898Skais rstart + SSL3_HDR_LEN, rec_sz, mp->b_wptr); 1479898Skais if (ret == CRYPTO_SUCCESS) { 1480898Skais ssl->seq_num[KSSL_WRITE]++; 1481898Skais mp->b_wptr += mac_sz; 1482898Skais rec_sz += mac_sz; 1483898Skais } else { 1484898Skais return (ret); 1485898Skais } 1486898Skais } 1487898Skais 1488898Skais if (spec->cipher_type == type_block) { 1489898Skais pad_sz = spec->cipher_bsize - 1490898Skais (rec_sz & (spec->cipher_bsize - 1)); 1491898Skais ASSERT(mp->b_wptr + pad_sz <= mp->b_datap->db_lim); 1492898Skais for (i = 0; i < pad_sz; i++) { 1493898Skais mp->b_wptr[i] = pad_sz - 1; 1494898Skais } 1495898Skais mp->b_wptr += pad_sz; 1496898Skais rec_sz += pad_sz; 1497898Skais } 1498898Skais 1499898Skais ASSERT(rec_sz <= SSL3_MAX_RECORD_LENGTH); 1500898Skais 1501898Skais U16_TO_BE16(rec_sz, rstart + 3); 1502898Skais 1503898Skais if (spec->cipher_ctx == 0) 1504898Skais return (ret); 1505898Skais 1506898Skais spec->cipher_data.cd_length = rec_sz; 1507898Skais spec->cipher_data.cd_raw.iov_base = (char *)(rstart + SSL3_HDR_LEN); 1508898Skais spec->cipher_data.cd_raw.iov_len = rec_sz; 1509898Skais /* One record at a time. Otherwise, gotta allocate the crypt_data_t */ 1510898Skais ret = crypto_encrypt_update(spec->cipher_ctx, &spec->cipher_data, 1511898Skais NULL, NULL); 1512898Skais #ifdef DEBUG 1513898Skais if (CRYPTO_ERR(ret)) { 1514898Skais cmn_err(CE_WARN, 1515898Skais "kssl_mac_encrypt_record: crypto_encrypt_update " 1516898Skais "error 0x%02X", ret); 1517898Skais } 1518898Skais #endif /* DEBUG */ 1519898Skais return (ret); 1520898Skais } 1521898Skais 1522898Skais void 1523898Skais kssl_send_alert(ssl_t *ssl, SSL3AlertLevel level, SSL3AlertDescription desc) 1524898Skais { 1525898Skais mblk_t *mp; 1526898Skais uchar_t *buf; 1527898Skais KSSLCipherSpec *spec; 1528898Skais 1529898Skais ASSERT(ssl != NULL); 1530898Skais 1531898Skais ssl->sendalert_level = level; 1532898Skais ssl->sendalert_desc = desc; 1533898Skais 1534898Skais if (level == alert_fatal) { 1535898Skais #ifdef DEBUG 1536898Skais cmn_err(CE_WARN, "sending an alert %d %d from %p\n", level, 1537898Skais desc, (void *)caller()); 1538898Skais #endif /* DEBUG */ 1539898Skais if (ssl->sid.cached == B_TRUE) { 1540898Skais kssl_uncache_sid(&ssl->sid, ssl->kssl_entry); 1541898Skais ssl->sid.cached = B_FALSE; 1542898Skais } 1543898Skais ssl->fatal_alert = B_TRUE; 1544898Skais KSSL_COUNTER(fatal_alerts, 1); 1545898Skais } else 1546898Skais KSSL_COUNTER(warning_alerts, 1); 1547898Skais 1548898Skais spec = &ssl->spec[KSSL_WRITE]; 1549898Skais 1550898Skais ASSERT(ssl->alert_sendbuf == NULL); 1551898Skais ssl->alert_sendbuf = mp = allocb(7 + spec->mac_hashsz + 1552898Skais spec->cipher_bsize, BPRI_HI); 1553898Skais if (mp == NULL) { 1554898Skais KSSL_COUNTER(alloc_fails, 1); 1555898Skais return; 1556898Skais } 1557898Skais buf = mp->b_wptr; 1558898Skais 1559898Skais /* 5 byte record header */ 1560898Skais buf[0] = content_alert; 1561898Skais buf[1] = ssl->major_version; 1562898Skais buf[2] = ssl->minor_version; 1563898Skais buf[3] = 0; 1564898Skais buf[4] = 2; 1565898Skais buf += SSL3_HDR_LEN; 1566898Skais 1567898Skais /* alert contents */ 1568898Skais buf[0] = (uchar_t)level; 1569898Skais buf[1] = (uchar_t)desc; 1570898Skais 1571898Skais mp->b_wptr = buf + 2; 1572898Skais } 1573898Skais 1574898Skais /* Assumes RSA encryption */ 1575898Skais static int 1576898Skais kssl_handle_client_key_exchange(ssl_t *ssl, mblk_t *mp, int msglen, 1577898Skais kssl_callback_t cbfn, void *arg) 1578898Skais { 1579898Skais char *buf; 1580898Skais uchar_t *pms; 1581898Skais size_t pmslen; 1582898Skais int allocated; 15832800Skrishna int err, rverr = ENOMEM; 15842800Skrishna kssl_entry_t *ep; 1585898Skais crypto_key_t *privkey; 1586898Skais crypto_data_t *wrapped_pms_data, *pms_data; 1587898Skais crypto_call_req_t creq, *creqp; 1588898Skais 15892800Skrishna ep = ssl->kssl_entry; 15902800Skrishna privkey = ep->ke_private_key; 1591898Skais if (privkey == NULL) { 15922800Skrishna return (ENOENT); 1593898Skais } 1594898Skais 1595898Skais ASSERT(ssl->msg.type == client_key_exchange); 1596898Skais ASSERT(ssl->hs_waitstate == wait_client_key); 1597898Skais 1598898Skais /* 1599898Skais * TLS adds an extra 2 byte length field before the data. 1600898Skais */ 1601898Skais if (IS_TLS(ssl)) { 1602898Skais msglen = (mp->b_rptr[0] << 8) | mp->b_rptr[1]; 1603898Skais mp->b_rptr += 2; 1604898Skais } 1605898Skais 1606898Skais /* 1607898Skais * Allocate all we need in one shot. about 300 bytes total, for 1608898Skais * 1024 bit RSA modulus. 1609898Skais * The buffer layout will be: pms_data, wrapped_pms_data, the 1610898Skais * value of the wrapped pms from the client, then room for the 1611898Skais * resulting decrypted premaster secret. 1612898Skais */ 1613898Skais allocated = 2 * (sizeof (crypto_data_t) + msglen); 1614898Skais buf = kmem_alloc(allocated, KM_NOSLEEP); 1615898Skais if (buf == NULL) { 1616898Skais return (ENOMEM); 1617898Skais } 1618898Skais 1619898Skais pms_data = (crypto_data_t *)buf; 1620898Skais wrapped_pms_data = &(((crypto_data_t *)buf)[1]); 1621898Skais 1622898Skais wrapped_pms_data->cd_format = pms_data->cd_format = CRYPTO_DATA_RAW; 1623898Skais wrapped_pms_data->cd_offset = pms_data->cd_offset = 0; 1624898Skais wrapped_pms_data->cd_length = pms_data->cd_length = msglen; 1625898Skais wrapped_pms_data->cd_miscdata = pms_data->cd_miscdata = NULL; 1626898Skais wrapped_pms_data->cd_raw.iov_len = pms_data->cd_raw.iov_len = msglen; 1627898Skais wrapped_pms_data->cd_raw.iov_base = buf + 2 * sizeof (crypto_data_t); 1628898Skais pms_data->cd_raw.iov_base = wrapped_pms_data->cd_raw.iov_base + msglen; 1629898Skais 1630898Skais bcopy(mp->b_rptr, wrapped_pms_data->cd_raw.iov_base, msglen); 1631898Skais mp->b_rptr += msglen; 1632898Skais 1633898Skais /* Proceed synchronously if out of interrupt and configured to do so */ 1634898Skais if ((kssl_synchronous) && (!servicing_interrupt())) { 1635898Skais creqp = NULL; 1636898Skais } else { 1637898Skais ssl->cke_callback_func = cbfn; 1638898Skais ssl->cke_callback_arg = arg; 1639898Skais creq.cr_flag = kssl_call_flag; 1640898Skais creq.cr_callback_func = kssl_cke_done; 1641898Skais creq.cr_callback_arg = ssl; 1642898Skais 1643898Skais /* The callback routine will release this one */ 1644898Skais KSSL_SSL_REFHOLD(ssl); 1645898Skais 1646898Skais creqp = &creq; 1647898Skais } 1648898Skais 16492800Skrishna if (ep->ke_is_nxkey) { 16502800Skrishna kssl_session_info_t *s; 16512800Skrishna 16522800Skrishna s = ep->ke_sessinfo; 16532800Skrishna err = CRYPTO_SUCCESS; 16542800Skrishna if (!s->is_valid_handle) { 16552800Skrishna /* Reauthenticate to the provider */ 16562800Skrishna if (s->do_reauth) { 16572800Skrishna err = kssl_get_obj_handle(ep); 16582800Skrishna if (err == CRYPTO_SUCCESS) { 16592800Skrishna s->is_valid_handle = B_TRUE; 16602800Skrishna s->do_reauth = B_FALSE; 16612800Skrishna } 16622800Skrishna } else 16632800Skrishna err = CRYPTO_FAILED; 16642800Skrishna } 16652800Skrishna 16662800Skrishna if (err == CRYPTO_SUCCESS) { 16672800Skrishna ASSERT(s->is_valid_handle); 16682800Skrishna err = crypto_decrypt_prov(s->prov, s->sid, 16692800Skrishna &rsa_x509_mech, wrapped_pms_data, &s->key, 16702800Skrishna NULL, pms_data, creqp); 16712800Skrishna } 16722800Skrishna 16732800Skrishna /* 16742800Skrishna * Deal with session specific errors. We translate to 16752800Skrishna * the closest errno. 16762800Skrishna */ 16772800Skrishna switch (err) { 16782800Skrishna case CRYPTO_KEY_HANDLE_INVALID: 16792800Skrishna case CRYPTO_SESSION_HANDLE_INVALID: 16802800Skrishna s->is_valid_handle = B_FALSE; 16812800Skrishna s->do_reauth = B_TRUE; 16822800Skrishna rverr = EINVAL; 16832800Skrishna break; 16842800Skrishna case CRYPTO_PIN_EXPIRED: 16852800Skrishna case CRYPTO_PIN_LOCKED: 16862800Skrishna rverr = EACCES; 16872800Skrishna break; 16882800Skrishna case CRYPTO_UNKNOWN_PROVIDER: 16892800Skrishna rverr = ENXIO; 16902800Skrishna break; 16912800Skrishna } 16922800Skrishna } else { 16932800Skrishna err = crypto_decrypt(&rsa_x509_mech, wrapped_pms_data, 16942800Skrishna privkey, NULL, pms_data, creqp); 16952800Skrishna } 1696898Skais 1697898Skais switch (err) { 1698898Skais case CRYPTO_SUCCESS: 1699898Skais break; 1700898Skais 1701898Skais case CRYPTO_QUEUED: 1702898Skais /* 1703898Skais * Finish the master secret then the rest of key material 1704898Skais * derivation later. 1705898Skais */ 1706898Skais ssl->job.kjob = creq.cr_reqid; 1707898Skais ssl->job.buf = buf; 1708898Skais ssl->job.buflen = allocated; 1709898Skais ssl->hs_waitstate = wait_client_key_done; 1710898Skais return (0); 1711898Skais default: 1712898Skais #ifdef DEBUG 1713898Skais cmn_err(CE_WARN, "kssl_handle_client_key_exchange: " 1714898Skais "crypto_decrypt error 0x%02X", err); 1715898Skais #endif /* DEBUG */ 1716898Skais kmem_free(buf, allocated); 17172800Skrishna return (rverr); 1718898Skais } 1719898Skais 1720898Skais pmslen = pms_data->cd_length; 1721898Skais pms = kssl_rsa_unwrap((uchar_t *)pms_data->cd_raw.iov_base, &pmslen); 1722898Skais 1723898Skais /* generate master key and save it in the ssl sid structure */ 1724898Skais if (IS_TLS(ssl)) { 1725898Skais err = kssl_generate_tls_ms(ssl, pms, pmslen); 1726898Skais if (!CRYPTO_ERR(err)) 1727898Skais err = kssl_generate_tls_keyblock(ssl); 1728898Skais } else { 1729898Skais kssl_generate_ssl_ms(ssl, pms, pmslen); 1730898Skais kssl_generate_keyblock(ssl); 1731898Skais } 1732898Skais 1733898Skais if (err == CRYPTO_SUCCESS) 1734898Skais ssl->hs_waitstate = wait_change_cipher; 1735898Skais 1736898Skais ssl->activeinput = B_FALSE; 1737898Skais 1738898Skais kmem_free(buf, allocated); 1739898Skais 1740898Skais return (0); 1741898Skais } 1742898Skais 1743898Skais static int 1744898Skais kssl_handle_finished(ssl_t *ssl, mblk_t *mp, int msglen) 1745898Skais { 1746898Skais int err; 1747898Skais size_t finish_len; 1748898Skais int hashcompare; 1749898Skais 1750898Skais ASSERT(ssl->msg.type == finished); 1751898Skais ASSERT(ssl->hs_waitstate == wait_finished); 1752898Skais 1753898Skais if (IS_TLS(ssl)) 1754898Skais finish_len = TLS_FINISHED_SIZE; 1755898Skais else 1756898Skais finish_len = KSSL_SSL3_FIN_MSGLEN; 1757898Skais 1758898Skais if (msglen != finish_len) { 1759898Skais kssl_send_alert(ssl, alert_fatal, illegal_parameter); 1760898Skais return (EBADMSG); 1761898Skais } 1762898Skais 1763898Skais if (IS_TLS(ssl)) { 1764898Skais hashcompare = bcmp(mp->b_rptr, ssl->hs_hashes.tlshash, 1765898Skais finish_len); 1766898Skais } else { 1767898Skais hashcompare = bcmp(mp->b_rptr, &ssl->hs_hashes, finish_len); 1768898Skais } 1769898Skais 1770898Skais /* The handshake hashes should be computed by now */ 1771898Skais if (hashcompare != 0) { 1772898Skais kssl_send_alert(ssl, alert_fatal, handshake_failure); 1773898Skais return (EBADMSG); 1774898Skais } 1775898Skais 1776898Skais mp->b_rptr += msglen; 1777898Skais 1778898Skais ssl->hs_waitstate = idle_handshake; 1779898Skais 1780898Skais if (ssl->resumed == B_TRUE) { 1781898Skais ssl->activeinput = B_FALSE; 1782898Skais return (0); 1783898Skais } 1784898Skais 1785898Skais err = kssl_send_change_cipher_specs(ssl); 1786898Skais if (err != 0) { 1787898Skais return (err); 1788898Skais } 1789898Skais err = kssl_send_finished(ssl, 0); 1790898Skais if (err != 0) { 1791898Skais return (err); 1792898Skais } 1793898Skais 1794898Skais ASSERT(ssl->sid.cached == B_FALSE); 1795898Skais ssl->sid.cached = B_TRUE; 1796898Skais kssl_cache_sid(&ssl->sid, ssl->kssl_entry); 1797898Skais ssl->activeinput = B_FALSE; 1798898Skais 1799898Skais return (0); 1800898Skais } 1801898Skais 1802898Skais #define KSSL2_CH_MIN_RECSZ (9) 1803898Skais 1804898Skais /* 1805898Skais * This method is needed to handle clients which send the 1806898Skais * SSLv2/SSLv3 handshake for backwards compat with SSLv2 servers. 1807898Skais * We are not really doing SSLv2 here, just handling the header 1808898Skais * and then switching to SSLv3. 1809898Skais */ 1810898Skais int 1811898Skais kssl_handle_v2client_hello(ssl_t *ssl, mblk_t *mp, int recsz) 1812898Skais { 1813898Skais uchar_t *recend; 1814898Skais int err; 1815898Skais SSL3AlertDescription desc = illegal_parameter; 1816898Skais uint_t randlen; 1817898Skais uint_t sidlen; 1818898Skais uint_t nsuites; 1819898Skais uchar_t *suitesp; 1820898Skais uchar_t *rand; 1821898Skais uint_t i, j; 1822898Skais uint16_t suite; 1823898Skais int ch_recsz = KSSL2_CH_MIN_RECSZ; 1824898Skais 1825898Skais ASSERT(mp->b_wptr >= mp->b_rptr + recsz); 1826898Skais ASSERT(ssl->hs_waitstate == wait_client_hello); 1827898Skais ASSERT(ssl->resumed == B_FALSE); 1828898Skais 1829898Skais if (recsz < ch_recsz) { 1830898Skais goto falert; 1831898Skais } 1832898Skais 1833898Skais MD5Init(&ssl->hs_md5); 1834898Skais SHA1Init(&ssl->hs_sha1); 1835898Skais 1836898Skais kssl_update_handshake_hashes(ssl, mp->b_rptr, recsz); 1837898Skais 1838898Skais recend = mp->b_rptr + recsz; 1839898Skais 1840898Skais if (*mp->b_rptr != 1) { 1841898Skais goto falert; 1842898Skais } 1843898Skais mp->b_rptr += 3; 1844898Skais 1845898Skais nsuites = ((uint_t)mp->b_rptr[0] << 8) + (uint_t)mp->b_rptr[1]; 1846898Skais sidlen = ((uint_t)mp->b_rptr[2] << 8) + (uint_t)mp->b_rptr[3]; 1847898Skais randlen = ((uint_t)mp->b_rptr[4] << 8) + (uint_t)mp->b_rptr[5]; 1848898Skais if (nsuites % 3 != 0) { 1849898Skais KSSL_DEBUG2_IF(kssl_debug, 1850898Skais "kssl_handle_v2client_hello nsuites = %d, error.", 1851898Skais nsuites); 1852898Skais goto falert; 1853898Skais } 1854898Skais if (randlen < SSL_MIN_CHALLENGE_BYTES || 1855898Skais randlen > SSL_MAX_CHALLENGE_BYTES) { 1856898Skais KSSL_DEBUG2_IF(kssl_debug, 1857898Skais "kssl_handle_v2client_hello randlen out of range: %d", 1858898Skais randlen); 1859898Skais goto falert; 1860898Skais } 1861898Skais mp->b_rptr += 6; 1862898Skais ch_recsz += nsuites + sidlen + randlen; 1863898Skais if (recsz != ch_recsz) { 1864898Skais goto falert; 1865898Skais } 1866898Skais suitesp = mp->b_rptr; 1867898Skais rand = suitesp + nsuites + sidlen; 1868898Skais if (randlen < SSL3_RANDOM_LENGTH) { 1869898Skais bzero(ssl->client_random, SSL3_RANDOM_LENGTH); 1870898Skais } 1871898Skais bcopy(rand, &ssl->client_random[SSL3_RANDOM_LENGTH - randlen], 1872898Skais randlen); 1873898Skais 1874898Skais for (i = 0; i < ssl->kssl_entry->kssl_cipherSuites_nentries; i++) { 1875898Skais suite = ssl->kssl_entry->kssl_cipherSuites[i]; 1876898Skais for (j = 0; j < nsuites; j += 3) { 1877898Skais if (suitesp[j] != 0) { 1878898Skais continue; 1879898Skais } 1880898Skais 1881898Skais if (suitesp[j + 1] == ((suite >> 8) & 0xff) && 1882898Skais suitesp[j + 2] == (suite & 0xff)) { 1883898Skais break; 1884898Skais } 1885898Skais } 1886898Skais if (j < nsuites) { 1887898Skais break; 1888898Skais } 1889898Skais } 1890898Skais if (i == ssl->kssl_entry->kssl_cipherSuites_nentries) { 1891898Skais KSSL_DEBUG1_IF(kssl_debug, "kssl_handle_v2client_hello - " 1892898Skais "cannot find SSLv2 cipher suite"); 1893898Skais ssl->activeinput = B_FALSE; 1894898Skais return (SSL_MISS); 1895898Skais } 1896898Skais 1897898Skais mp->b_rptr = recend; 1898898Skais 1899898Skais for (i = 0; i < cipher_suite_defs_nentries; i++) { 1900898Skais if (suite == cipher_suite_defs[i].suite) { 1901898Skais break; 1902898Skais } 1903898Skais } 1904898Skais 1905898Skais ASSERT(i < cipher_suite_defs_nentries); 1906898Skais 1907898Skais ssl->pending_cipher_suite = suite; 1908898Skais ssl->pending_malg = cipher_suite_defs[i].malg; 1909898Skais ssl->pending_calg = cipher_suite_defs[i].calg; 1910898Skais ssl->pending_keyblksz = cipher_suite_defs[i].keyblksz; 1911898Skais 1912898Skais ASSERT(ssl->sid.cached == B_FALSE); 1913898Skais 1914898Skais (void) random_get_pseudo_bytes(ssl->sid.session_id, 1915898Skais SSL3_SESSIONID_BYTES); 1916898Skais ssl->sid.client_addr = ssl->faddr; 1917898Skais ssl->sid.cipher_suite = suite; 1918898Skais 1919898Skais err = kssl_send_server_hello(ssl); 1920898Skais if (err != 0) { 1921898Skais return (err); 1922898Skais } 1923898Skais err = kssl_send_certificate_and_server_hello_done(ssl); 1924898Skais if (err != 0) { 1925898Skais return (err); 1926898Skais } 1927898Skais KSSL_COUNTER(full_handshakes, 1); 1928898Skais ssl->hs_waitstate = wait_client_key; 1929898Skais ssl->activeinput = B_FALSE; 1930898Skais return (0); 1931898Skais 1932898Skais falert: 1933898Skais kssl_send_alert(ssl, alert_fatal, desc); 1934898Skais ssl->activeinput = B_FALSE; 1935898Skais return (EBADMSG); 1936898Skais } 1937898Skais 1938898Skais /* 1939898Skais * Call back routine for asynchronously submitted RSA decryption jobs. 1940898Skais * The routine retreived the pre-master secret, and proceeds to generate 1941898Skais * the remaining key materials. 1942898Skais */ 1943898Skais static void 1944898Skais kssl_cke_done(void *arg, int status) 1945898Skais { 1946898Skais int ret = 0; 1947898Skais uchar_t *pms; 1948898Skais size_t pmslen; 1949898Skais crypto_data_t *pms_data; 1950898Skais kssl_cmd_t kssl_cmd = KSSL_CMD_NONE; 1951898Skais ssl_t *ssl = (ssl_t *)arg; 1952898Skais mblk_t *alertmp; 1953898Skais kssl_callback_t cbfn; 1954898Skais void *cbarg; 1955898Skais 1956898Skais mutex_enter(&ssl->kssl_lock); 1957898Skais 1958898Skais ASSERT(ssl->msg.type == client_key_exchange); 1959898Skais ASSERT(ssl->hs_waitstate == wait_client_key_done); 1960898Skais 1961898Skais if (status != CRYPTO_SUCCESS) { 1962898Skais kssl_send_alert(ssl, alert_fatal, decrypt_error); 1963898Skais kssl_cmd = KSSL_CMD_SEND; 1964898Skais goto out; 1965898Skais } 1966898Skais 1967898Skais pms_data = (crypto_data_t *)(ssl->job.buf); 1968898Skais 1969898Skais ASSERT(pms_data != NULL); 1970898Skais 1971898Skais pmslen = pms_data->cd_length; 1972898Skais pms = kssl_rsa_unwrap((uchar_t *)pms_data->cd_raw.iov_base, &pmslen); 1973898Skais 1974898Skais /* generate master key and save it in the ssl sid structure */ 1975898Skais if (IS_TLS(ssl)) { 1976898Skais ret = kssl_generate_tls_ms(ssl, pms, pmslen); 1977898Skais if (!CRYPTO_ERR(ret)) 1978898Skais ret = kssl_generate_tls_keyblock(ssl); 1979898Skais } else { 1980898Skais kssl_generate_ssl_ms(ssl, pms, pmslen); 1981898Skais kssl_generate_keyblock(ssl); 1982898Skais } 1983898Skais 1984898Skais if (ret == CRYPTO_SUCCESS) 1985898Skais ssl->hs_waitstate = wait_change_cipher; 1986898Skais 1987898Skais out: 1988898Skais kmem_free(ssl->job.buf, ssl->job.buflen); 1989898Skais 1990898Skais ssl->job.kjob = 0; 1991898Skais ssl->job.buf = NULL; 1992898Skais ssl->job.buflen = 0; 1993898Skais 1994898Skais ssl->activeinput = B_FALSE; 1995898Skais 1996898Skais /* If we're the only ones left, then we won't callback */ 1997898Skais if (ssl->kssl_refcnt == 1) { 1998898Skais mutex_exit(&ssl->kssl_lock); 1999898Skais KSSL_SSL_REFRELE(ssl); 2000898Skais return; 2001898Skais } 2002898Skais 2003898Skais cbfn = ssl->cke_callback_func; 2004898Skais cbarg = ssl->cke_callback_arg; 2005898Skais alertmp = ssl->alert_sendbuf; 2006898Skais ssl->alert_sendbuf = NULL; 2007898Skais 2008898Skais mutex_exit(&ssl->kssl_lock); 2009898Skais 2010898Skais KSSL_SSL_REFRELE(ssl); 2011898Skais 2012898Skais /* Now call the callback routine */ 2013898Skais (*(cbfn))(cbarg, alertmp, kssl_cmd); 2014898Skais } 2015898Skais 2016898Skais /* 2017898Skais * Returns the first complete contiguous record out of rec_ass_head 2018898Skais * The record is returned in a separate contiguous mblk, rec_ass_head is 2019898Skais * left pointing to the next record in the queue. 2020898Skais * 2021898Skais * The output looks as follows: 2022898Skais * 2023898Skais * |--------|---------- .... -----|<---------->|<----------->|--- ... ---| 2024898Skais * ^ ^ ^ mac_size pad_size ^ 2025898Skais * | |___ b_rptr b_wptr __| | 2026898Skais * | | 2027898Skais * |___ db_base db_lim ___| 2028898Skais */ 2029898Skais mblk_t * 2030898Skais kssl_get_next_record(ssl_t *ssl) 2031898Skais { 2032898Skais mblk_t *mp, *retmp; 2033898Skais int rhsz = SSL3_HDR_LEN; 2034898Skais uint16_t rec_sz; 2035898Skais int mpsz, total_size; 2036898Skais SSL3ContentType content_type; 2037898Skais 2038898Skais ASSERT(MUTEX_HELD(&ssl->kssl_lock)); 2039898Skais 2040898Skais mp = ssl->rec_ass_head; 2041898Skais if (mp == NULL) 2042898Skais return (NULL); 2043898Skais 2044898Skais /* Fast path: when mp has at least a complete record */ 2045898Skais if (MBLKL(mp) < rhsz) { 2046898Skais /* Not even a complete header in there yet */ 2047898Skais if (msgdsize(mp) < rhsz) { 2048898Skais return (NULL); 2049898Skais } 2050898Skais 2051898Skais if (!pullupmsg(mp, rhsz)) { 2052898Skais kssl_send_alert(ssl, alert_fatal, internal_error); 2053898Skais freemsg(mp); 2054898Skais ssl->rec_ass_head = ssl->rec_ass_tail = NULL; 2055898Skais return (NULL); 2056898Skais } 2057898Skais } 2058898Skais content_type = (SSL3ContentType)mp->b_rptr[0]; 2059898Skais if (content_type == content_handshake_v2) { 2060898Skais rec_sz = (uint16_t)mp->b_rptr[1]; 2061898Skais rhsz = 2; 2062898Skais } else { 2063898Skais uint8_t *rec_sz_p = (uint8_t *)mp->b_rptr + 3; 2064898Skais rec_sz = BE16_TO_U16(rec_sz_p); 2065898Skais } 2066898Skais 2067898Skais /* 2068898Skais * same tests as above. Only rare very fragmented cases will 2069898Skais * incur the cost of msgdsize() and msgpullup(). Well formed 2070898Skais * packets will fall in the most frequent fast path. 2071898Skais */ 2072898Skais total_size = rhsz + rec_sz; 2073898Skais 2074898Skais /* 2075898Skais * Missing: defensive against record fabricated with longer than 2076898Skais * MAX record length. 2077898Skais */ 2078898Skais if (MBLKL(mp) < total_size) { 2079898Skais /* Not a complete record yet. Keep accumulating */ 2080898Skais if (msgdsize(mp) < total_size) { 2081898Skais return (NULL); 2082898Skais } 2083898Skais 2084898Skais if (!pullupmsg(mp, total_size)) { 2085898Skais kssl_send_alert(ssl, alert_fatal, internal_error); 2086898Skais freemsg(mp); 2087898Skais ssl->rec_ass_head = ssl->rec_ass_tail = NULL; 2088898Skais return (NULL); 2089898Skais } 2090898Skais } 2091898Skais mpsz = MBLKL(mp); /* could've changed after the pullup */ 2092898Skais 2093898Skais if (mpsz > total_size) { 2094898Skais /* gotta allocate a new block */ 2095898Skais if ((retmp = dupb(mp)) == NULL) { 2096898Skais kssl_send_alert(ssl, alert_fatal, internal_error); 2097898Skais freemsg(mp); 2098898Skais ssl->rec_ass_head = ssl->rec_ass_tail = NULL; 2099898Skais return (NULL); 2100898Skais } 2101898Skais 2102898Skais retmp->b_wptr = retmp->b_rptr + total_size; 2103898Skais mp->b_rptr += total_size; 2104898Skais ssl->rec_ass_head = mp; 2105898Skais } else { 2106898Skais ASSERT(mpsz == total_size); 2107898Skais ssl->rec_ass_head = mp->b_cont; 2108898Skais mp->b_cont = NULL; 2109898Skais retmp = mp; 2110898Skais } 2111898Skais /* Adjust the tail */ 2112898Skais if ((mp = ssl->rec_ass_tail = ssl->rec_ass_head) != NULL) { 2113898Skais for (; mp->b_cont != NULL; mp = mp->b_cont) { 2114898Skais ssl->rec_ass_tail = mp->b_cont; 2115898Skais } 2116898Skais } 2117898Skais 2118898Skais return (retmp); 2119898Skais } 2120898Skais 2121898Skais 2122898Skais static void 2123898Skais kssl_mblksfree(ssl_t *ssl) 2124898Skais { 2125898Skais 2126898Skais ASSERT(ssl != NULL); 2127898Skais 2128898Skais if (ssl->rec_ass_head != NULL) { 2129898Skais freemsg(ssl->rec_ass_head); 2130898Skais } 2131898Skais ssl->rec_ass_head = NULL; 2132898Skais ssl->rec_ass_tail = NULL; 2133898Skais 2134898Skais if (ssl->msg.head != NULL) { 2135898Skais freemsg(ssl->msg.head); 2136898Skais } 2137898Skais ssl->msg.head = NULL; 2138898Skais ssl->msg.tail = NULL; 2139898Skais 2140898Skais if (ssl->handshake_sendbuf != NULL) { 2141898Skais freemsg(ssl->handshake_sendbuf); 2142898Skais ssl->handshake_sendbuf = NULL; 2143898Skais } 2144898Skais if (ssl->alert_sendbuf != NULL) { 2145898Skais freemsg(ssl->alert_sendbuf); 2146898Skais ssl->alert_sendbuf = NULL; 2147898Skais } 2148898Skais } 2149898Skais 2150898Skais static void 2151898Skais kssl_specsfree(ssl_t *ssl) 2152898Skais { 2153898Skais KSSLCipherSpec *spec = &ssl->spec[KSSL_READ]; 2154898Skais 2155898Skais if (spec->cipher_ctx != NULL) { 2156898Skais crypto_cancel_ctx(spec->cipher_ctx); 2157898Skais spec->cipher_ctx = 0; 2158898Skais } 2159898Skais 2160898Skais spec = &ssl->spec[KSSL_WRITE]; 2161898Skais 2162898Skais if (spec->cipher_ctx != NULL) { 2163898Skais crypto_cancel_ctx(spec->cipher_ctx); 2164898Skais spec->cipher_ctx = 0; 2165898Skais } 2166898Skais } 2167898Skais 2168898Skais /* 2169898Skais * Frees the ssl structure (aka the context of an SSL session). 2170898Skais * Any pending crypto jobs are cancelled. 2171898Skais * Any initiated crypto contexts are freed as well. 2172898Skais */ 2173898Skais void 2174898Skais kssl_free_context(ssl_t *ssl) 2175898Skais { 2176898Skais ASSERT(ssl != NULL); 2177898Skais if (!(MUTEX_HELD(&ssl->kssl_lock))) { 2178898Skais /* we're coming from an external API entry point */ 2179898Skais mutex_enter(&ssl->kssl_lock); 2180898Skais } 2181898Skais 2182898Skais if (ssl->job.kjob != NULL) { 2183898Skais crypto_cancel_req(ssl->job.kjob); 2184898Skais kmem_free(ssl->job.buf, ssl->job.buflen); 2185898Skais 2186898Skais ssl->job.kjob = 0; 2187898Skais ssl->job.buf = NULL; 2188898Skais ssl->job.buflen = 0; 2189898Skais } 2190898Skais 2191898Skais kssl_mblksfree(ssl); 2192898Skais kssl_specsfree(ssl); 2193898Skais 2194898Skais KSSL_ENTRY_REFRELE(ssl->kssl_entry); 2195898Skais ssl->kssl_entry = NULL; 2196898Skais 2197898Skais mutex_exit(&ssl->kssl_lock); 2198898Skais 2199898Skais kmem_cache_free(kssl_cache, ssl); 2200898Skais kssl_cache_count--; 2201898Skais } 2202