16d49e1aeSJan Lentfer /*
26d49e1aeSJan Lentfer * TLSv1 client - write handshake message
3*a1157835SDaniel Fojt * Copyright (c) 2006-2015, Jouni Malinen <j@w1.fi>
46d49e1aeSJan Lentfer *
53ff40c12SJohn Marino * This software may be distributed under the terms of the BSD license.
63ff40c12SJohn Marino * See README for more details.
76d49e1aeSJan Lentfer */
86d49e1aeSJan Lentfer
96d49e1aeSJan Lentfer #include "includes.h"
106d49e1aeSJan Lentfer
116d49e1aeSJan Lentfer #include "common.h"
123ff40c12SJohn Marino #include "crypto/md5.h"
133ff40c12SJohn Marino #include "crypto/sha1.h"
143ff40c12SJohn Marino #include "crypto/sha256.h"
153ff40c12SJohn Marino #include "crypto/tls.h"
163ff40c12SJohn Marino #include "crypto/random.h"
176d49e1aeSJan Lentfer #include "x509v3.h"
186d49e1aeSJan Lentfer #include "tlsv1_common.h"
196d49e1aeSJan Lentfer #include "tlsv1_record.h"
206d49e1aeSJan Lentfer #include "tlsv1_client.h"
216d49e1aeSJan Lentfer #include "tlsv1_client_i.h"
226d49e1aeSJan Lentfer
236d49e1aeSJan Lentfer
tls_client_cert_chain_der_len(struct tlsv1_client * conn)246d49e1aeSJan Lentfer static size_t tls_client_cert_chain_der_len(struct tlsv1_client *conn)
256d49e1aeSJan Lentfer {
266d49e1aeSJan Lentfer size_t len = 0;
276d49e1aeSJan Lentfer struct x509_certificate *cert;
286d49e1aeSJan Lentfer
296d49e1aeSJan Lentfer if (conn->cred == NULL)
306d49e1aeSJan Lentfer return 0;
316d49e1aeSJan Lentfer
326d49e1aeSJan Lentfer cert = conn->cred->cert;
336d49e1aeSJan Lentfer while (cert) {
346d49e1aeSJan Lentfer len += 3 + cert->cert_len;
356d49e1aeSJan Lentfer if (x509_certificate_self_signed(cert))
366d49e1aeSJan Lentfer break;
376d49e1aeSJan Lentfer cert = x509_certificate_get_subject(conn->cred->trusted_certs,
386d49e1aeSJan Lentfer &cert->issuer);
396d49e1aeSJan Lentfer }
406d49e1aeSJan Lentfer
416d49e1aeSJan Lentfer return len;
426d49e1aeSJan Lentfer }
436d49e1aeSJan Lentfer
446d49e1aeSJan Lentfer
tls_send_client_hello(struct tlsv1_client * conn,size_t * out_len)456d49e1aeSJan Lentfer u8 * tls_send_client_hello(struct tlsv1_client *conn, size_t *out_len)
466d49e1aeSJan Lentfer {
476d49e1aeSJan Lentfer u8 *hello, *end, *pos, *hs_length, *hs_start, *rhdr;
486d49e1aeSJan Lentfer struct os_time now;
496d49e1aeSJan Lentfer size_t len, i;
50*a1157835SDaniel Fojt u8 *ext_start;
51*a1157835SDaniel Fojt u16 tls_version = TLS_VERSION;
526d49e1aeSJan Lentfer
53*a1157835SDaniel Fojt /* Pick the highest locally enabled TLS version */
54*a1157835SDaniel Fojt #ifdef CONFIG_TLSV12
55*a1157835SDaniel Fojt if ((conn->flags & TLS_CONN_DISABLE_TLSv1_2) &&
56*a1157835SDaniel Fojt tls_version == TLS_VERSION_1_2)
57*a1157835SDaniel Fojt tls_version = TLS_VERSION_1_1;
58*a1157835SDaniel Fojt #endif /* CONFIG_TLSV12 */
59*a1157835SDaniel Fojt #ifdef CONFIG_TLSV11
60*a1157835SDaniel Fojt if ((conn->flags & TLS_CONN_DISABLE_TLSv1_1) &&
61*a1157835SDaniel Fojt tls_version == TLS_VERSION_1_1)
62*a1157835SDaniel Fojt tls_version = TLS_VERSION_1;
63*a1157835SDaniel Fojt #endif /* CONFIG_TLSV11 */
64*a1157835SDaniel Fojt if ((conn->flags & TLS_CONN_DISABLE_TLSv1_0) &&
65*a1157835SDaniel Fojt tls_version == TLS_VERSION_1) {
66*a1157835SDaniel Fojt wpa_printf(MSG_INFO, "TLSv1: No TLS version allowed");
67*a1157835SDaniel Fojt return NULL;
68*a1157835SDaniel Fojt }
69*a1157835SDaniel Fojt
70*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG, "TLSv1: Send ClientHello (ver %s)",
71*a1157835SDaniel Fojt tls_version_str(tls_version));
726d49e1aeSJan Lentfer *out_len = 0;
736d49e1aeSJan Lentfer
746d49e1aeSJan Lentfer os_get_time(&now);
75*a1157835SDaniel Fojt #ifdef TEST_FUZZ
76*a1157835SDaniel Fojt now.sec = 0xfffefdfc;
77*a1157835SDaniel Fojt #endif /* TEST_FUZZ */
786d49e1aeSJan Lentfer WPA_PUT_BE32(conn->client_random, now.sec);
793ff40c12SJohn Marino if (random_get_bytes(conn->client_random + 4, TLS_RANDOM_LEN - 4)) {
806d49e1aeSJan Lentfer wpa_printf(MSG_ERROR, "TLSv1: Could not generate "
816d49e1aeSJan Lentfer "client_random");
826d49e1aeSJan Lentfer return NULL;
836d49e1aeSJan Lentfer }
846d49e1aeSJan Lentfer wpa_hexdump(MSG_MSGDUMP, "TLSv1: client_random",
856d49e1aeSJan Lentfer conn->client_random, TLS_RANDOM_LEN);
866d49e1aeSJan Lentfer
87*a1157835SDaniel Fojt len = 150 + conn->num_cipher_suites * 2 + conn->client_hello_ext_len;
886d49e1aeSJan Lentfer hello = os_malloc(len);
896d49e1aeSJan Lentfer if (hello == NULL)
906d49e1aeSJan Lentfer return NULL;
916d49e1aeSJan Lentfer end = hello + len;
926d49e1aeSJan Lentfer
936d49e1aeSJan Lentfer rhdr = hello;
946d49e1aeSJan Lentfer pos = rhdr + TLS_RECORD_HEADER_LEN;
956d49e1aeSJan Lentfer
966d49e1aeSJan Lentfer /* opaque fragment[TLSPlaintext.length] */
976d49e1aeSJan Lentfer
986d49e1aeSJan Lentfer /* Handshake */
996d49e1aeSJan Lentfer hs_start = pos;
1006d49e1aeSJan Lentfer /* HandshakeType msg_type */
1016d49e1aeSJan Lentfer *pos++ = TLS_HANDSHAKE_TYPE_CLIENT_HELLO;
1026d49e1aeSJan Lentfer /* uint24 length (to be filled) */
1036d49e1aeSJan Lentfer hs_length = pos;
1046d49e1aeSJan Lentfer pos += 3;
1056d49e1aeSJan Lentfer /* body - ClientHello */
1066d49e1aeSJan Lentfer /* ProtocolVersion client_version */
107*a1157835SDaniel Fojt WPA_PUT_BE16(pos, tls_version);
1086d49e1aeSJan Lentfer pos += 2;
1096d49e1aeSJan Lentfer /* Random random: uint32 gmt_unix_time, opaque random_bytes */
1106d49e1aeSJan Lentfer os_memcpy(pos, conn->client_random, TLS_RANDOM_LEN);
1116d49e1aeSJan Lentfer pos += TLS_RANDOM_LEN;
1126d49e1aeSJan Lentfer /* SessionID session_id */
1136d49e1aeSJan Lentfer *pos++ = conn->session_id_len;
1146d49e1aeSJan Lentfer os_memcpy(pos, conn->session_id, conn->session_id_len);
1156d49e1aeSJan Lentfer pos += conn->session_id_len;
1166d49e1aeSJan Lentfer /* CipherSuite cipher_suites<2..2^16-1> */
1176d49e1aeSJan Lentfer WPA_PUT_BE16(pos, 2 * conn->num_cipher_suites);
1186d49e1aeSJan Lentfer pos += 2;
1196d49e1aeSJan Lentfer for (i = 0; i < conn->num_cipher_suites; i++) {
1206d49e1aeSJan Lentfer WPA_PUT_BE16(pos, conn->cipher_suites[i]);
1216d49e1aeSJan Lentfer pos += 2;
1226d49e1aeSJan Lentfer }
1236d49e1aeSJan Lentfer /* CompressionMethod compression_methods<1..2^8-1> */
1246d49e1aeSJan Lentfer *pos++ = 1;
1256d49e1aeSJan Lentfer *pos++ = TLS_COMPRESSION_NULL;
1266d49e1aeSJan Lentfer
127*a1157835SDaniel Fojt /* Extension */
128*a1157835SDaniel Fojt ext_start = pos;
129*a1157835SDaniel Fojt pos += 2;
130*a1157835SDaniel Fojt
131*a1157835SDaniel Fojt #ifdef CONFIG_TLSV12
132*a1157835SDaniel Fojt if (conn->rl.tls_version >= TLS_VERSION_1_2) {
133*a1157835SDaniel Fojt /*
134*a1157835SDaniel Fojt * Add signature_algorithms extension since we support only
135*a1157835SDaniel Fojt * SHA256 (and not the default SHA1) with TLSv1.2.
136*a1157835SDaniel Fojt */
137*a1157835SDaniel Fojt /* ExtensionsType extension_type = signature_algorithms(13) */
138*a1157835SDaniel Fojt WPA_PUT_BE16(pos, TLS_EXT_SIGNATURE_ALGORITHMS);
139*a1157835SDaniel Fojt pos += 2;
140*a1157835SDaniel Fojt /* opaque extension_data<0..2^16-1> length */
141*a1157835SDaniel Fojt WPA_PUT_BE16(pos, 8);
142*a1157835SDaniel Fojt pos += 2;
143*a1157835SDaniel Fojt /* supported_signature_algorithms<2..2^16-2> length */
144*a1157835SDaniel Fojt WPA_PUT_BE16(pos, 6);
145*a1157835SDaniel Fojt pos += 2;
146*a1157835SDaniel Fojt /* supported_signature_algorithms */
147*a1157835SDaniel Fojt *pos++ = TLS_HASH_ALG_SHA512;
148*a1157835SDaniel Fojt *pos++ = TLS_SIGN_ALG_RSA;
149*a1157835SDaniel Fojt *pos++ = TLS_HASH_ALG_SHA384;
150*a1157835SDaniel Fojt *pos++ = TLS_SIGN_ALG_RSA;
151*a1157835SDaniel Fojt *pos++ = TLS_HASH_ALG_SHA256;
152*a1157835SDaniel Fojt *pos++ = TLS_SIGN_ALG_RSA;
153*a1157835SDaniel Fojt }
154*a1157835SDaniel Fojt #endif /* CONFIG_TLSV12 */
155*a1157835SDaniel Fojt
1566d49e1aeSJan Lentfer if (conn->client_hello_ext) {
1576d49e1aeSJan Lentfer os_memcpy(pos, conn->client_hello_ext,
1586d49e1aeSJan Lentfer conn->client_hello_ext_len);
1596d49e1aeSJan Lentfer pos += conn->client_hello_ext_len;
1606d49e1aeSJan Lentfer }
1616d49e1aeSJan Lentfer
162*a1157835SDaniel Fojt if (conn->flags & TLS_CONN_REQUEST_OCSP) {
163*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG,
164*a1157835SDaniel Fojt "TLSv1: Add status_request extension for OCSP stapling");
165*a1157835SDaniel Fojt /* ExtensionsType extension_type = status_request(5) */
166*a1157835SDaniel Fojt WPA_PUT_BE16(pos, TLS_EXT_STATUS_REQUEST);
167*a1157835SDaniel Fojt pos += 2;
168*a1157835SDaniel Fojt /* opaque extension_data<0..2^16-1> length */
169*a1157835SDaniel Fojt WPA_PUT_BE16(pos, 5);
170*a1157835SDaniel Fojt pos += 2;
171*a1157835SDaniel Fojt
172*a1157835SDaniel Fojt /*
173*a1157835SDaniel Fojt * RFC 6066, 8:
174*a1157835SDaniel Fojt * struct {
175*a1157835SDaniel Fojt * CertificateStatusType status_type;
176*a1157835SDaniel Fojt * select (status_type) {
177*a1157835SDaniel Fojt * case ocsp: OCSPStatusRequest;
178*a1157835SDaniel Fojt * } request;
179*a1157835SDaniel Fojt * } CertificateStatusRequest;
180*a1157835SDaniel Fojt *
181*a1157835SDaniel Fojt * enum { ocsp(1), (255) } CertificateStatusType;
182*a1157835SDaniel Fojt */
183*a1157835SDaniel Fojt *pos++ = 1; /* status_type = ocsp(1) */
184*a1157835SDaniel Fojt
185*a1157835SDaniel Fojt /*
186*a1157835SDaniel Fojt * struct {
187*a1157835SDaniel Fojt * ResponderID responder_id_list<0..2^16-1>;
188*a1157835SDaniel Fojt * Extensions request_extensions;
189*a1157835SDaniel Fojt * } OCSPStatusRequest;
190*a1157835SDaniel Fojt *
191*a1157835SDaniel Fojt * opaque ResponderID<1..2^16-1>;
192*a1157835SDaniel Fojt * opaque Extensions<0..2^16-1>;
193*a1157835SDaniel Fojt */
194*a1157835SDaniel Fojt WPA_PUT_BE16(pos, 0); /* responder_id_list(empty) */
195*a1157835SDaniel Fojt pos += 2;
196*a1157835SDaniel Fojt WPA_PUT_BE16(pos, 0); /* request_extensions(empty) */
197*a1157835SDaniel Fojt pos += 2;
198*a1157835SDaniel Fojt
199*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG,
200*a1157835SDaniel Fojt "TLSv1: Add status_request_v2 extension for OCSP stapling");
201*a1157835SDaniel Fojt /* ExtensionsType extension_type = status_request_v2(17) */
202*a1157835SDaniel Fojt WPA_PUT_BE16(pos, TLS_EXT_STATUS_REQUEST_V2);
203*a1157835SDaniel Fojt pos += 2;
204*a1157835SDaniel Fojt /* opaque extension_data<0..2^16-1> length */
205*a1157835SDaniel Fojt WPA_PUT_BE16(pos, 7);
206*a1157835SDaniel Fojt pos += 2;
207*a1157835SDaniel Fojt
208*a1157835SDaniel Fojt /*
209*a1157835SDaniel Fojt * RFC 6961, 2.2:
210*a1157835SDaniel Fojt * struct {
211*a1157835SDaniel Fojt * CertificateStatusType status_type;
212*a1157835SDaniel Fojt * uint16 request_length;
213*a1157835SDaniel Fojt * select (status_type) {
214*a1157835SDaniel Fojt * case ocsp: OCSPStatusRequest;
215*a1157835SDaniel Fojt * case ocsp_multi: OCSPStatusRequest;
216*a1157835SDaniel Fojt * } request;
217*a1157835SDaniel Fojt * } CertificateStatusRequestItemV2;
218*a1157835SDaniel Fojt *
219*a1157835SDaniel Fojt * enum { ocsp(1), ocsp_multi(2), (255) } CertificateStatusType;
220*a1157835SDaniel Fojt *
221*a1157835SDaniel Fojt * struct {
222*a1157835SDaniel Fojt * CertificateStatusRequestItemV2
223*a1157835SDaniel Fojt * certificate_status_req_list<1..2^16-1>;
224*a1157835SDaniel Fojt * } CertificateStatusRequestListV2;
225*a1157835SDaniel Fojt */
226*a1157835SDaniel Fojt
227*a1157835SDaniel Fojt /* certificate_status_req_list<1..2^16-1> */
228*a1157835SDaniel Fojt WPA_PUT_BE16(pos, 5);
229*a1157835SDaniel Fojt pos += 2;
230*a1157835SDaniel Fojt
231*a1157835SDaniel Fojt /* CertificateStatusRequestItemV2 */
232*a1157835SDaniel Fojt *pos++ = 2; /* status_type = ocsp_multi(2) */
233*a1157835SDaniel Fojt /* OCSPStatusRequest as shown above for v1 */
234*a1157835SDaniel Fojt WPA_PUT_BE16(pos, 0); /* responder_id_list(empty) */
235*a1157835SDaniel Fojt pos += 2;
236*a1157835SDaniel Fojt WPA_PUT_BE16(pos, 0); /* request_extensions(empty) */
237*a1157835SDaniel Fojt pos += 2;
238*a1157835SDaniel Fojt }
239*a1157835SDaniel Fojt
240*a1157835SDaniel Fojt if (pos == ext_start + 2)
241*a1157835SDaniel Fojt pos -= 2; /* no extensions */
242*a1157835SDaniel Fojt else
243*a1157835SDaniel Fojt WPA_PUT_BE16(ext_start, pos - ext_start - 2);
244*a1157835SDaniel Fojt
2456d49e1aeSJan Lentfer WPA_PUT_BE24(hs_length, pos - hs_length - 3);
2466d49e1aeSJan Lentfer tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
2476d49e1aeSJan Lentfer
2486d49e1aeSJan Lentfer if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
2493ff40c12SJohn Marino rhdr, end - rhdr, hs_start, pos - hs_start,
2503ff40c12SJohn Marino out_len) < 0) {
2516d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "TLSv1: Failed to create TLS record");
2526d49e1aeSJan Lentfer tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
2536d49e1aeSJan Lentfer TLS_ALERT_INTERNAL_ERROR);
2546d49e1aeSJan Lentfer os_free(hello);
2556d49e1aeSJan Lentfer return NULL;
2566d49e1aeSJan Lentfer }
2576d49e1aeSJan Lentfer
2586d49e1aeSJan Lentfer conn->state = SERVER_HELLO;
2596d49e1aeSJan Lentfer
2606d49e1aeSJan Lentfer return hello;
2616d49e1aeSJan Lentfer }
2626d49e1aeSJan Lentfer
2636d49e1aeSJan Lentfer
tls_write_client_certificate(struct tlsv1_client * conn,u8 ** msgpos,u8 * end)2646d49e1aeSJan Lentfer static int tls_write_client_certificate(struct tlsv1_client *conn,
2656d49e1aeSJan Lentfer u8 **msgpos, u8 *end)
2666d49e1aeSJan Lentfer {
2676d49e1aeSJan Lentfer u8 *pos, *rhdr, *hs_start, *hs_length, *cert_start;
2686d49e1aeSJan Lentfer size_t rlen;
2696d49e1aeSJan Lentfer struct x509_certificate *cert;
2706d49e1aeSJan Lentfer
2716d49e1aeSJan Lentfer pos = *msgpos;
272*a1157835SDaniel Fojt if (TLS_RECORD_HEADER_LEN + 1 + 3 + 3 > end - pos) {
273*a1157835SDaniel Fojt tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
274*a1157835SDaniel Fojt TLS_ALERT_INTERNAL_ERROR);
275*a1157835SDaniel Fojt return -1;
276*a1157835SDaniel Fojt }
2776d49e1aeSJan Lentfer
2786d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "TLSv1: Send Certificate");
2796d49e1aeSJan Lentfer rhdr = pos;
2806d49e1aeSJan Lentfer pos += TLS_RECORD_HEADER_LEN;
2816d49e1aeSJan Lentfer
2826d49e1aeSJan Lentfer /* opaque fragment[TLSPlaintext.length] */
2836d49e1aeSJan Lentfer
2846d49e1aeSJan Lentfer /* Handshake */
2856d49e1aeSJan Lentfer hs_start = pos;
2866d49e1aeSJan Lentfer /* HandshakeType msg_type */
2876d49e1aeSJan Lentfer *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE;
2886d49e1aeSJan Lentfer /* uint24 length (to be filled) */
2896d49e1aeSJan Lentfer hs_length = pos;
2906d49e1aeSJan Lentfer pos += 3;
2916d49e1aeSJan Lentfer /* body - Certificate */
2926d49e1aeSJan Lentfer /* uint24 length (to be filled) */
2936d49e1aeSJan Lentfer cert_start = pos;
2946d49e1aeSJan Lentfer pos += 3;
2956d49e1aeSJan Lentfer cert = conn->cred ? conn->cred->cert : NULL;
2966d49e1aeSJan Lentfer while (cert) {
297*a1157835SDaniel Fojt if (3 + cert->cert_len > (size_t) (end - pos)) {
2986d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space "
2996d49e1aeSJan Lentfer "for Certificate (cert_len=%lu left=%lu)",
3006d49e1aeSJan Lentfer (unsigned long) cert->cert_len,
3016d49e1aeSJan Lentfer (unsigned long) (end - pos));
3026d49e1aeSJan Lentfer tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
3036d49e1aeSJan Lentfer TLS_ALERT_INTERNAL_ERROR);
3046d49e1aeSJan Lentfer return -1;
3056d49e1aeSJan Lentfer }
3066d49e1aeSJan Lentfer WPA_PUT_BE24(pos, cert->cert_len);
3076d49e1aeSJan Lentfer pos += 3;
3086d49e1aeSJan Lentfer os_memcpy(pos, cert->cert_start, cert->cert_len);
3096d49e1aeSJan Lentfer pos += cert->cert_len;
3106d49e1aeSJan Lentfer
3116d49e1aeSJan Lentfer if (x509_certificate_self_signed(cert))
3126d49e1aeSJan Lentfer break;
3136d49e1aeSJan Lentfer cert = x509_certificate_get_subject(conn->cred->trusted_certs,
3146d49e1aeSJan Lentfer &cert->issuer);
3156d49e1aeSJan Lentfer }
3166d49e1aeSJan Lentfer if (conn->cred == NULL || cert == conn->cred->cert || cert == NULL) {
3176d49e1aeSJan Lentfer /*
3186d49e1aeSJan Lentfer * Client was not configured with all the needed certificates
3196d49e1aeSJan Lentfer * to form a full certificate chain. The server may fail to
3206d49e1aeSJan Lentfer * validate the chain unless it is configured with all the
3216d49e1aeSJan Lentfer * missing CA certificates.
3226d49e1aeSJan Lentfer */
3236d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "TLSv1: Full client certificate chain "
3246d49e1aeSJan Lentfer "not configured - validation may fail");
3256d49e1aeSJan Lentfer }
3266d49e1aeSJan Lentfer WPA_PUT_BE24(cert_start, pos - cert_start - 3);
3276d49e1aeSJan Lentfer
3286d49e1aeSJan Lentfer WPA_PUT_BE24(hs_length, pos - hs_length - 3);
3296d49e1aeSJan Lentfer
3306d49e1aeSJan Lentfer if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
3313ff40c12SJohn Marino rhdr, end - rhdr, hs_start, pos - hs_start,
3323ff40c12SJohn Marino &rlen) < 0) {
3336d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record");
3346d49e1aeSJan Lentfer tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
3356d49e1aeSJan Lentfer TLS_ALERT_INTERNAL_ERROR);
3366d49e1aeSJan Lentfer return -1;
3376d49e1aeSJan Lentfer }
3386d49e1aeSJan Lentfer pos = rhdr + rlen;
3396d49e1aeSJan Lentfer
3406d49e1aeSJan Lentfer tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
3416d49e1aeSJan Lentfer
3426d49e1aeSJan Lentfer *msgpos = pos;
3436d49e1aeSJan Lentfer
3446d49e1aeSJan Lentfer return 0;
3456d49e1aeSJan Lentfer }
3466d49e1aeSJan Lentfer
3476d49e1aeSJan Lentfer
tlsv1_key_x_dh(struct tlsv1_client * conn,u8 ** pos,u8 * end)348*a1157835SDaniel Fojt static int tlsv1_key_x_dh(struct tlsv1_client *conn, u8 **pos, u8 *end)
3496d49e1aeSJan Lentfer {
3506d49e1aeSJan Lentfer /* ClientDiffieHellmanPublic */
3516d49e1aeSJan Lentfer u8 *csecret, *csecret_start, *dh_yc, *shared;
3526d49e1aeSJan Lentfer size_t csecret_len, dh_yc_len, shared_len;
3536d49e1aeSJan Lentfer
3546d49e1aeSJan Lentfer csecret_len = conn->dh_p_len;
3556d49e1aeSJan Lentfer csecret = os_malloc(csecret_len);
3566d49e1aeSJan Lentfer if (csecret == NULL) {
3576d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate "
3586d49e1aeSJan Lentfer "memory for Yc (Diffie-Hellman)");
3596d49e1aeSJan Lentfer tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
3606d49e1aeSJan Lentfer TLS_ALERT_INTERNAL_ERROR);
3616d49e1aeSJan Lentfer return -1;
3626d49e1aeSJan Lentfer }
3633ff40c12SJohn Marino if (random_get_bytes(csecret, csecret_len)) {
3646d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "TLSv1: Failed to get random "
3656d49e1aeSJan Lentfer "data for Diffie-Hellman");
3666d49e1aeSJan Lentfer tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
3676d49e1aeSJan Lentfer TLS_ALERT_INTERNAL_ERROR);
3686d49e1aeSJan Lentfer os_free(csecret);
3696d49e1aeSJan Lentfer return -1;
3706d49e1aeSJan Lentfer }
3716d49e1aeSJan Lentfer
3726d49e1aeSJan Lentfer if (os_memcmp(csecret, conn->dh_p, csecret_len) > 0)
3736d49e1aeSJan Lentfer csecret[0] = 0; /* make sure Yc < p */
3746d49e1aeSJan Lentfer
3756d49e1aeSJan Lentfer csecret_start = csecret;
3766d49e1aeSJan Lentfer while (csecret_len > 1 && *csecret_start == 0) {
3776d49e1aeSJan Lentfer csecret_start++;
3786d49e1aeSJan Lentfer csecret_len--;
3796d49e1aeSJan Lentfer }
3806d49e1aeSJan Lentfer wpa_hexdump_key(MSG_DEBUG, "TLSv1: DH client's secret value",
3816d49e1aeSJan Lentfer csecret_start, csecret_len);
3826d49e1aeSJan Lentfer
3836d49e1aeSJan Lentfer /* Yc = g^csecret mod p */
3846d49e1aeSJan Lentfer dh_yc_len = conn->dh_p_len;
3856d49e1aeSJan Lentfer dh_yc = os_malloc(dh_yc_len);
3866d49e1aeSJan Lentfer if (dh_yc == NULL) {
3876d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate "
3886d49e1aeSJan Lentfer "memory for Diffie-Hellman");
3896d49e1aeSJan Lentfer tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
3906d49e1aeSJan Lentfer TLS_ALERT_INTERNAL_ERROR);
3916d49e1aeSJan Lentfer os_free(csecret);
3926d49e1aeSJan Lentfer return -1;
3936d49e1aeSJan Lentfer }
3946d49e1aeSJan Lentfer if (crypto_mod_exp(conn->dh_g, conn->dh_g_len,
3956d49e1aeSJan Lentfer csecret_start, csecret_len,
3966d49e1aeSJan Lentfer conn->dh_p, conn->dh_p_len,
3976d49e1aeSJan Lentfer dh_yc, &dh_yc_len)) {
3986d49e1aeSJan Lentfer tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
3996d49e1aeSJan Lentfer TLS_ALERT_INTERNAL_ERROR);
4006d49e1aeSJan Lentfer os_free(csecret);
4016d49e1aeSJan Lentfer os_free(dh_yc);
4026d49e1aeSJan Lentfer return -1;
4036d49e1aeSJan Lentfer }
4046d49e1aeSJan Lentfer
4056d49e1aeSJan Lentfer wpa_hexdump(MSG_DEBUG, "TLSv1: DH Yc (client's public value)",
4066d49e1aeSJan Lentfer dh_yc, dh_yc_len);
4076d49e1aeSJan Lentfer
408*a1157835SDaniel Fojt if (end - *pos < 2) {
409*a1157835SDaniel Fojt tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
410*a1157835SDaniel Fojt TLS_ALERT_INTERNAL_ERROR);
411*a1157835SDaniel Fojt os_free(csecret);
412*a1157835SDaniel Fojt os_free(dh_yc);
413*a1157835SDaniel Fojt return -1;
414*a1157835SDaniel Fojt }
4156d49e1aeSJan Lentfer WPA_PUT_BE16(*pos, dh_yc_len);
4166d49e1aeSJan Lentfer *pos += 2;
417*a1157835SDaniel Fojt if (dh_yc_len > (size_t) (end - *pos)) {
4186d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "TLSv1: Not enough room in the "
4196d49e1aeSJan Lentfer "message buffer for Yc");
4206d49e1aeSJan Lentfer tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
4216d49e1aeSJan Lentfer TLS_ALERT_INTERNAL_ERROR);
4226d49e1aeSJan Lentfer os_free(csecret);
4236d49e1aeSJan Lentfer os_free(dh_yc);
4246d49e1aeSJan Lentfer return -1;
4256d49e1aeSJan Lentfer }
4266d49e1aeSJan Lentfer os_memcpy(*pos, dh_yc, dh_yc_len);
4276d49e1aeSJan Lentfer *pos += dh_yc_len;
4286d49e1aeSJan Lentfer os_free(dh_yc);
4296d49e1aeSJan Lentfer
4306d49e1aeSJan Lentfer shared_len = conn->dh_p_len;
4316d49e1aeSJan Lentfer shared = os_malloc(shared_len);
4326d49e1aeSJan Lentfer if (shared == NULL) {
4336d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "TLSv1: Could not allocate memory for "
4346d49e1aeSJan Lentfer "DH");
4356d49e1aeSJan Lentfer tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
4366d49e1aeSJan Lentfer TLS_ALERT_INTERNAL_ERROR);
4376d49e1aeSJan Lentfer os_free(csecret);
4386d49e1aeSJan Lentfer return -1;
4396d49e1aeSJan Lentfer }
4406d49e1aeSJan Lentfer
4416d49e1aeSJan Lentfer /* shared = Ys^csecret mod p */
4426d49e1aeSJan Lentfer if (crypto_mod_exp(conn->dh_ys, conn->dh_ys_len,
4436d49e1aeSJan Lentfer csecret_start, csecret_len,
4446d49e1aeSJan Lentfer conn->dh_p, conn->dh_p_len,
4456d49e1aeSJan Lentfer shared, &shared_len)) {
4466d49e1aeSJan Lentfer tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
4476d49e1aeSJan Lentfer TLS_ALERT_INTERNAL_ERROR);
4486d49e1aeSJan Lentfer os_free(csecret);
4496d49e1aeSJan Lentfer os_free(shared);
4506d49e1aeSJan Lentfer return -1;
4516d49e1aeSJan Lentfer }
4526d49e1aeSJan Lentfer wpa_hexdump_key(MSG_DEBUG, "TLSv1: Shared secret from DH key exchange",
4536d49e1aeSJan Lentfer shared, shared_len);
4546d49e1aeSJan Lentfer
4556d49e1aeSJan Lentfer os_memset(csecret_start, 0, csecret_len);
4566d49e1aeSJan Lentfer os_free(csecret);
4576d49e1aeSJan Lentfer if (tls_derive_keys(conn, shared, shared_len)) {
4586d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys");
4596d49e1aeSJan Lentfer tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
4606d49e1aeSJan Lentfer TLS_ALERT_INTERNAL_ERROR);
4616d49e1aeSJan Lentfer os_free(shared);
4626d49e1aeSJan Lentfer return -1;
4636d49e1aeSJan Lentfer }
4646d49e1aeSJan Lentfer os_memset(shared, 0, shared_len);
4656d49e1aeSJan Lentfer os_free(shared);
4666d49e1aeSJan Lentfer tlsv1_client_free_dh(conn);
4676d49e1aeSJan Lentfer return 0;
4686d49e1aeSJan Lentfer }
4696d49e1aeSJan Lentfer
4706d49e1aeSJan Lentfer
tlsv1_key_x_rsa(struct tlsv1_client * conn,u8 ** pos,u8 * end)4716d49e1aeSJan Lentfer static int tlsv1_key_x_rsa(struct tlsv1_client *conn, u8 **pos, u8 *end)
4726d49e1aeSJan Lentfer {
4736d49e1aeSJan Lentfer u8 pre_master_secret[TLS_PRE_MASTER_SECRET_LEN];
4746d49e1aeSJan Lentfer size_t clen;
4756d49e1aeSJan Lentfer int res;
4766d49e1aeSJan Lentfer
4776d49e1aeSJan Lentfer if (tls_derive_pre_master_secret(pre_master_secret) < 0 ||
4786d49e1aeSJan Lentfer tls_derive_keys(conn, pre_master_secret,
4796d49e1aeSJan Lentfer TLS_PRE_MASTER_SECRET_LEN)) {
4806d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys");
4816d49e1aeSJan Lentfer tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
4826d49e1aeSJan Lentfer TLS_ALERT_INTERNAL_ERROR);
4836d49e1aeSJan Lentfer return -1;
4846d49e1aeSJan Lentfer }
4856d49e1aeSJan Lentfer
4866d49e1aeSJan Lentfer /* EncryptedPreMasterSecret */
4876d49e1aeSJan Lentfer if (conn->server_rsa_key == NULL) {
4886d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "TLSv1: No server RSA key to "
4896d49e1aeSJan Lentfer "use for encrypting pre-master secret");
4906d49e1aeSJan Lentfer tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
4916d49e1aeSJan Lentfer TLS_ALERT_INTERNAL_ERROR);
4926d49e1aeSJan Lentfer return -1;
4936d49e1aeSJan Lentfer }
4946d49e1aeSJan Lentfer
4956d49e1aeSJan Lentfer /* RSA encrypted value is encoded with PKCS #1 v1.5 block type 2. */
4966d49e1aeSJan Lentfer *pos += 2;
4976d49e1aeSJan Lentfer clen = end - *pos;
4986d49e1aeSJan Lentfer res = crypto_public_key_encrypt_pkcs1_v15(
4996d49e1aeSJan Lentfer conn->server_rsa_key,
5006d49e1aeSJan Lentfer pre_master_secret, TLS_PRE_MASTER_SECRET_LEN,
5016d49e1aeSJan Lentfer *pos, &clen);
5026d49e1aeSJan Lentfer os_memset(pre_master_secret, 0, TLS_PRE_MASTER_SECRET_LEN);
5036d49e1aeSJan Lentfer if (res < 0) {
5046d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "TLSv1: RSA encryption failed");
5056d49e1aeSJan Lentfer tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
5066d49e1aeSJan Lentfer TLS_ALERT_INTERNAL_ERROR);
5076d49e1aeSJan Lentfer return -1;
5086d49e1aeSJan Lentfer }
5096d49e1aeSJan Lentfer WPA_PUT_BE16(*pos - 2, clen);
5106d49e1aeSJan Lentfer wpa_hexdump(MSG_MSGDUMP, "TLSv1: Encrypted pre_master_secret",
5116d49e1aeSJan Lentfer *pos, clen);
5126d49e1aeSJan Lentfer *pos += clen;
5136d49e1aeSJan Lentfer
5146d49e1aeSJan Lentfer return 0;
5156d49e1aeSJan Lentfer }
5166d49e1aeSJan Lentfer
5176d49e1aeSJan Lentfer
tls_write_client_key_exchange(struct tlsv1_client * conn,u8 ** msgpos,u8 * end)5186d49e1aeSJan Lentfer static int tls_write_client_key_exchange(struct tlsv1_client *conn,
5196d49e1aeSJan Lentfer u8 **msgpos, u8 *end)
5206d49e1aeSJan Lentfer {
5216d49e1aeSJan Lentfer u8 *pos, *rhdr, *hs_start, *hs_length;
5226d49e1aeSJan Lentfer size_t rlen;
5236d49e1aeSJan Lentfer tls_key_exchange keyx;
5246d49e1aeSJan Lentfer const struct tls_cipher_suite *suite;
5256d49e1aeSJan Lentfer
5266d49e1aeSJan Lentfer suite = tls_get_cipher_suite(conn->rl.cipher_suite);
5276d49e1aeSJan Lentfer if (suite == NULL)
5286d49e1aeSJan Lentfer keyx = TLS_KEY_X_NULL;
5296d49e1aeSJan Lentfer else
5306d49e1aeSJan Lentfer keyx = suite->key_exchange;
5316d49e1aeSJan Lentfer
5326d49e1aeSJan Lentfer pos = *msgpos;
5336d49e1aeSJan Lentfer
5346d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "TLSv1: Send ClientKeyExchange");
5356d49e1aeSJan Lentfer
5366d49e1aeSJan Lentfer rhdr = pos;
5376d49e1aeSJan Lentfer pos += TLS_RECORD_HEADER_LEN;
5386d49e1aeSJan Lentfer
5396d49e1aeSJan Lentfer /* opaque fragment[TLSPlaintext.length] */
5406d49e1aeSJan Lentfer
5416d49e1aeSJan Lentfer /* Handshake */
5426d49e1aeSJan Lentfer hs_start = pos;
5436d49e1aeSJan Lentfer /* HandshakeType msg_type */
5446d49e1aeSJan Lentfer *pos++ = TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE;
5456d49e1aeSJan Lentfer /* uint24 length (to be filled) */
5466d49e1aeSJan Lentfer hs_length = pos;
5476d49e1aeSJan Lentfer pos += 3;
5486d49e1aeSJan Lentfer /* body - ClientKeyExchange */
549*a1157835SDaniel Fojt if (keyx == TLS_KEY_X_DH_anon || keyx == TLS_KEY_X_DHE_RSA) {
550*a1157835SDaniel Fojt if (tlsv1_key_x_dh(conn, &pos, end) < 0)
5516d49e1aeSJan Lentfer return -1;
5526d49e1aeSJan Lentfer } else {
5536d49e1aeSJan Lentfer if (tlsv1_key_x_rsa(conn, &pos, end) < 0)
5546d49e1aeSJan Lentfer return -1;
5556d49e1aeSJan Lentfer }
5566d49e1aeSJan Lentfer
5576d49e1aeSJan Lentfer WPA_PUT_BE24(hs_length, pos - hs_length - 3);
5586d49e1aeSJan Lentfer
5596d49e1aeSJan Lentfer if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
5603ff40c12SJohn Marino rhdr, end - rhdr, hs_start, pos - hs_start,
5613ff40c12SJohn Marino &rlen) < 0) {
5626d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record");
5636d49e1aeSJan Lentfer tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
5646d49e1aeSJan Lentfer TLS_ALERT_INTERNAL_ERROR);
5656d49e1aeSJan Lentfer return -1;
5666d49e1aeSJan Lentfer }
5676d49e1aeSJan Lentfer pos = rhdr + rlen;
5686d49e1aeSJan Lentfer tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
5696d49e1aeSJan Lentfer
5706d49e1aeSJan Lentfer *msgpos = pos;
5716d49e1aeSJan Lentfer
5726d49e1aeSJan Lentfer return 0;
5736d49e1aeSJan Lentfer }
5746d49e1aeSJan Lentfer
5756d49e1aeSJan Lentfer
tls_write_client_certificate_verify(struct tlsv1_client * conn,u8 ** msgpos,u8 * end)5766d49e1aeSJan Lentfer static int tls_write_client_certificate_verify(struct tlsv1_client *conn,
5776d49e1aeSJan Lentfer u8 **msgpos, u8 *end)
5786d49e1aeSJan Lentfer {
5796d49e1aeSJan Lentfer u8 *pos, *rhdr, *hs_start, *hs_length, *signed_start;
5806d49e1aeSJan Lentfer size_t rlen, hlen, clen;
5813ff40c12SJohn Marino u8 hash[100], *hpos;
5826d49e1aeSJan Lentfer
5836d49e1aeSJan Lentfer pos = *msgpos;
5846d49e1aeSJan Lentfer
5856d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "TLSv1: Send CertificateVerify");
5866d49e1aeSJan Lentfer rhdr = pos;
5876d49e1aeSJan Lentfer pos += TLS_RECORD_HEADER_LEN;
5886d49e1aeSJan Lentfer
5896d49e1aeSJan Lentfer /* Handshake */
5906d49e1aeSJan Lentfer hs_start = pos;
5916d49e1aeSJan Lentfer /* HandshakeType msg_type */
5926d49e1aeSJan Lentfer *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE_VERIFY;
5936d49e1aeSJan Lentfer /* uint24 length (to be filled) */
5946d49e1aeSJan Lentfer hs_length = pos;
5956d49e1aeSJan Lentfer pos += 3;
5966d49e1aeSJan Lentfer
5976d49e1aeSJan Lentfer /*
5986d49e1aeSJan Lentfer * RFC 2246: 7.4.3 and 7.4.8:
5996d49e1aeSJan Lentfer * Signature signature
6006d49e1aeSJan Lentfer *
6016d49e1aeSJan Lentfer * RSA:
6026d49e1aeSJan Lentfer * digitally-signed struct {
6036d49e1aeSJan Lentfer * opaque md5_hash[16];
6046d49e1aeSJan Lentfer * opaque sha_hash[20];
6056d49e1aeSJan Lentfer * };
6066d49e1aeSJan Lentfer *
6076d49e1aeSJan Lentfer * DSA:
6086d49e1aeSJan Lentfer * digitally-signed struct {
6096d49e1aeSJan Lentfer * opaque sha_hash[20];
6106d49e1aeSJan Lentfer * };
6116d49e1aeSJan Lentfer *
6126d49e1aeSJan Lentfer * The hash values are calculated over all handshake messages sent or
6136d49e1aeSJan Lentfer * received starting at ClientHello up to, but not including, this
6146d49e1aeSJan Lentfer * CertificateVerify message, including the type and length fields of
6156d49e1aeSJan Lentfer * the handshake messages.
6166d49e1aeSJan Lentfer */
6176d49e1aeSJan Lentfer
6186d49e1aeSJan Lentfer hpos = hash;
6196d49e1aeSJan Lentfer
6203ff40c12SJohn Marino #ifdef CONFIG_TLSV12
6213ff40c12SJohn Marino if (conn->rl.tls_version == TLS_VERSION_1_2) {
6223ff40c12SJohn Marino hlen = SHA256_MAC_LEN;
6233ff40c12SJohn Marino if (conn->verify.sha256_cert == NULL ||
6243ff40c12SJohn Marino crypto_hash_finish(conn->verify.sha256_cert, hpos, &hlen) <
6253ff40c12SJohn Marino 0) {
6263ff40c12SJohn Marino conn->verify.sha256_cert = NULL;
6273ff40c12SJohn Marino tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
6283ff40c12SJohn Marino TLS_ALERT_INTERNAL_ERROR);
6293ff40c12SJohn Marino return -1;
6303ff40c12SJohn Marino }
6313ff40c12SJohn Marino conn->verify.sha256_cert = NULL;
6323ff40c12SJohn Marino
6333ff40c12SJohn Marino /*
6343ff40c12SJohn Marino * RFC 3447, A.2.4 RSASSA-PKCS1-v1_5
6353ff40c12SJohn Marino *
6363ff40c12SJohn Marino * DigestInfo ::= SEQUENCE {
6373ff40c12SJohn Marino * digestAlgorithm DigestAlgorithm,
6383ff40c12SJohn Marino * digest OCTET STRING
6393ff40c12SJohn Marino * }
6403ff40c12SJohn Marino *
6413ff40c12SJohn Marino * SHA-256 OID: sha256WithRSAEncryption ::= {pkcs-1 11}
6423ff40c12SJohn Marino *
6433ff40c12SJohn Marino * DER encoded DigestInfo for SHA256 per RFC 3447:
6443ff40c12SJohn Marino * 30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20 ||
6453ff40c12SJohn Marino * H
6463ff40c12SJohn Marino */
6473ff40c12SJohn Marino os_memmove(hash + 19, hash, hlen);
6483ff40c12SJohn Marino hlen += 19;
6493ff40c12SJohn Marino os_memcpy(hash, "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65"
6503ff40c12SJohn Marino "\x03\x04\x02\x01\x05\x00\x04\x20", 19);
6513ff40c12SJohn Marino } else {
6523ff40c12SJohn Marino #endif /* CONFIG_TLSV12 */
6533ff40c12SJohn Marino
6546d49e1aeSJan Lentfer hlen = MD5_MAC_LEN;
6556d49e1aeSJan Lentfer if (conn->verify.md5_cert == NULL ||
656*a1157835SDaniel Fojt crypto_hash_finish(conn->verify.md5_cert, hpos, &hlen) < 0) {
6576d49e1aeSJan Lentfer tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
6586d49e1aeSJan Lentfer TLS_ALERT_INTERNAL_ERROR);
6596d49e1aeSJan Lentfer conn->verify.md5_cert = NULL;
6606d49e1aeSJan Lentfer crypto_hash_finish(conn->verify.sha1_cert, NULL, NULL);
6616d49e1aeSJan Lentfer conn->verify.sha1_cert = NULL;
6626d49e1aeSJan Lentfer return -1;
6636d49e1aeSJan Lentfer }
6646d49e1aeSJan Lentfer hpos += MD5_MAC_LEN;
6656d49e1aeSJan Lentfer
6666d49e1aeSJan Lentfer conn->verify.md5_cert = NULL;
6676d49e1aeSJan Lentfer hlen = SHA1_MAC_LEN;
6686d49e1aeSJan Lentfer if (conn->verify.sha1_cert == NULL ||
6696d49e1aeSJan Lentfer crypto_hash_finish(conn->verify.sha1_cert, hpos, &hlen) < 0) {
6706d49e1aeSJan Lentfer conn->verify.sha1_cert = NULL;
6716d49e1aeSJan Lentfer tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
6726d49e1aeSJan Lentfer TLS_ALERT_INTERNAL_ERROR);
6736d49e1aeSJan Lentfer return -1;
6746d49e1aeSJan Lentfer }
6756d49e1aeSJan Lentfer conn->verify.sha1_cert = NULL;
6766d49e1aeSJan Lentfer
6776d49e1aeSJan Lentfer hlen += MD5_MAC_LEN;
6786d49e1aeSJan Lentfer
6793ff40c12SJohn Marino #ifdef CONFIG_TLSV12
6803ff40c12SJohn Marino }
6813ff40c12SJohn Marino #endif /* CONFIG_TLSV12 */
6823ff40c12SJohn Marino
6836d49e1aeSJan Lentfer wpa_hexdump(MSG_MSGDUMP, "TLSv1: CertificateVerify hash", hash, hlen);
6846d49e1aeSJan Lentfer
6853ff40c12SJohn Marino #ifdef CONFIG_TLSV12
6863ff40c12SJohn Marino if (conn->rl.tls_version >= TLS_VERSION_1_2) {
6873ff40c12SJohn Marino /*
6883ff40c12SJohn Marino * RFC 5246, 4.7:
6893ff40c12SJohn Marino * TLS v1.2 adds explicit indication of the used signature and
6903ff40c12SJohn Marino * hash algorithms.
6913ff40c12SJohn Marino *
6923ff40c12SJohn Marino * struct {
6933ff40c12SJohn Marino * HashAlgorithm hash;
6943ff40c12SJohn Marino * SignatureAlgorithm signature;
6953ff40c12SJohn Marino * } SignatureAndHashAlgorithm;
6963ff40c12SJohn Marino */
6973ff40c12SJohn Marino *pos++ = TLS_HASH_ALG_SHA256;
6983ff40c12SJohn Marino *pos++ = TLS_SIGN_ALG_RSA;
6993ff40c12SJohn Marino }
7003ff40c12SJohn Marino #endif /* CONFIG_TLSV12 */
7013ff40c12SJohn Marino
7026d49e1aeSJan Lentfer /*
7036d49e1aeSJan Lentfer * RFC 2246, 4.7:
7046d49e1aeSJan Lentfer * In digital signing, one-way hash functions are used as input for a
7056d49e1aeSJan Lentfer * signing algorithm. A digitally-signed element is encoded as an
7066d49e1aeSJan Lentfer * opaque vector <0..2^16-1>, where the length is specified by the
7076d49e1aeSJan Lentfer * signing algorithm and key.
7086d49e1aeSJan Lentfer *
7096d49e1aeSJan Lentfer * In RSA signing, a 36-byte structure of two hashes (one SHA and one
7106d49e1aeSJan Lentfer * MD5) is signed (encrypted with the private key). It is encoded with
7116d49e1aeSJan Lentfer * PKCS #1 block type 0 or type 1 as described in [PKCS1].
7126d49e1aeSJan Lentfer */
7136d49e1aeSJan Lentfer signed_start = pos; /* length to be filled */
7146d49e1aeSJan Lentfer pos += 2;
7156d49e1aeSJan Lentfer clen = end - pos;
7166d49e1aeSJan Lentfer if (conn->cred == NULL ||
7176d49e1aeSJan Lentfer crypto_private_key_sign_pkcs1(conn->cred->key, hash, hlen,
7186d49e1aeSJan Lentfer pos, &clen) < 0) {
7196d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "TLSv1: Failed to sign hash (PKCS #1)");
7206d49e1aeSJan Lentfer tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
7216d49e1aeSJan Lentfer TLS_ALERT_INTERNAL_ERROR);
7226d49e1aeSJan Lentfer return -1;
7236d49e1aeSJan Lentfer }
7246d49e1aeSJan Lentfer WPA_PUT_BE16(signed_start, clen);
7256d49e1aeSJan Lentfer
7266d49e1aeSJan Lentfer pos += clen;
7276d49e1aeSJan Lentfer
7286d49e1aeSJan Lentfer WPA_PUT_BE24(hs_length, pos - hs_length - 3);
7296d49e1aeSJan Lentfer
7306d49e1aeSJan Lentfer if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
7313ff40c12SJohn Marino rhdr, end - rhdr, hs_start, pos - hs_start,
7323ff40c12SJohn Marino &rlen) < 0) {
7336d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record");
7346d49e1aeSJan Lentfer tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
7356d49e1aeSJan Lentfer TLS_ALERT_INTERNAL_ERROR);
7366d49e1aeSJan Lentfer return -1;
7376d49e1aeSJan Lentfer }
7386d49e1aeSJan Lentfer pos = rhdr + rlen;
7396d49e1aeSJan Lentfer
7406d49e1aeSJan Lentfer tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
7416d49e1aeSJan Lentfer
7426d49e1aeSJan Lentfer *msgpos = pos;
7436d49e1aeSJan Lentfer
7446d49e1aeSJan Lentfer return 0;
7456d49e1aeSJan Lentfer }
7466d49e1aeSJan Lentfer
7476d49e1aeSJan Lentfer
tls_write_client_change_cipher_spec(struct tlsv1_client * conn,u8 ** msgpos,u8 * end)7486d49e1aeSJan Lentfer static int tls_write_client_change_cipher_spec(struct tlsv1_client *conn,
7496d49e1aeSJan Lentfer u8 **msgpos, u8 *end)
7506d49e1aeSJan Lentfer {
7516d49e1aeSJan Lentfer size_t rlen;
7523ff40c12SJohn Marino u8 payload[1];
7536d49e1aeSJan Lentfer
7546d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "TLSv1: Send ChangeCipherSpec");
7553ff40c12SJohn Marino
7563ff40c12SJohn Marino payload[0] = TLS_CHANGE_CIPHER_SPEC;
7573ff40c12SJohn Marino
7586d49e1aeSJan Lentfer if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC,
7593ff40c12SJohn Marino *msgpos, end - *msgpos, payload, sizeof(payload),
7603ff40c12SJohn Marino &rlen) < 0) {
7616d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record");
7626d49e1aeSJan Lentfer tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
7636d49e1aeSJan Lentfer TLS_ALERT_INTERNAL_ERROR);
7646d49e1aeSJan Lentfer return -1;
7656d49e1aeSJan Lentfer }
7666d49e1aeSJan Lentfer
7676d49e1aeSJan Lentfer if (tlsv1_record_change_write_cipher(&conn->rl) < 0) {
7686d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "TLSv1: Failed to set write cipher for "
7696d49e1aeSJan Lentfer "record layer");
7706d49e1aeSJan Lentfer tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
7716d49e1aeSJan Lentfer TLS_ALERT_INTERNAL_ERROR);
7726d49e1aeSJan Lentfer return -1;
7736d49e1aeSJan Lentfer }
7746d49e1aeSJan Lentfer
7753ff40c12SJohn Marino *msgpos += rlen;
7766d49e1aeSJan Lentfer
7776d49e1aeSJan Lentfer return 0;
7786d49e1aeSJan Lentfer }
7796d49e1aeSJan Lentfer
7806d49e1aeSJan Lentfer
tls_write_client_finished(struct tlsv1_client * conn,u8 ** msgpos,u8 * end)7816d49e1aeSJan Lentfer static int tls_write_client_finished(struct tlsv1_client *conn,
7826d49e1aeSJan Lentfer u8 **msgpos, u8 *end)
7836d49e1aeSJan Lentfer {
7843ff40c12SJohn Marino u8 *pos, *hs_start;
7856d49e1aeSJan Lentfer size_t rlen, hlen;
7863ff40c12SJohn Marino u8 verify_data[1 + 3 + TLS_VERIFY_DATA_LEN];
7876d49e1aeSJan Lentfer u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN];
7886d49e1aeSJan Lentfer
7896d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "TLSv1: Send Finished");
7906d49e1aeSJan Lentfer
7916d49e1aeSJan Lentfer /* Encrypted Handshake Message: Finished */
7926d49e1aeSJan Lentfer
7933ff40c12SJohn Marino #ifdef CONFIG_TLSV12
7943ff40c12SJohn Marino if (conn->rl.tls_version >= TLS_VERSION_1_2) {
7953ff40c12SJohn Marino hlen = SHA256_MAC_LEN;
7963ff40c12SJohn Marino if (conn->verify.sha256_client == NULL ||
7973ff40c12SJohn Marino crypto_hash_finish(conn->verify.sha256_client, hash, &hlen)
7983ff40c12SJohn Marino < 0) {
7993ff40c12SJohn Marino tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
8003ff40c12SJohn Marino TLS_ALERT_INTERNAL_ERROR);
8013ff40c12SJohn Marino conn->verify.sha256_client = NULL;
8023ff40c12SJohn Marino return -1;
8033ff40c12SJohn Marino }
8043ff40c12SJohn Marino conn->verify.sha256_client = NULL;
8053ff40c12SJohn Marino } else {
8063ff40c12SJohn Marino #endif /* CONFIG_TLSV12 */
8073ff40c12SJohn Marino
8086d49e1aeSJan Lentfer hlen = MD5_MAC_LEN;
8096d49e1aeSJan Lentfer if (conn->verify.md5_client == NULL ||
8106d49e1aeSJan Lentfer crypto_hash_finish(conn->verify.md5_client, hash, &hlen) < 0) {
8116d49e1aeSJan Lentfer tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
8126d49e1aeSJan Lentfer TLS_ALERT_INTERNAL_ERROR);
8136d49e1aeSJan Lentfer conn->verify.md5_client = NULL;
8146d49e1aeSJan Lentfer crypto_hash_finish(conn->verify.sha1_client, NULL, NULL);
8156d49e1aeSJan Lentfer conn->verify.sha1_client = NULL;
8166d49e1aeSJan Lentfer return -1;
8176d49e1aeSJan Lentfer }
8186d49e1aeSJan Lentfer conn->verify.md5_client = NULL;
8196d49e1aeSJan Lentfer hlen = SHA1_MAC_LEN;
8206d49e1aeSJan Lentfer if (conn->verify.sha1_client == NULL ||
8216d49e1aeSJan Lentfer crypto_hash_finish(conn->verify.sha1_client, hash + MD5_MAC_LEN,
8226d49e1aeSJan Lentfer &hlen) < 0) {
8236d49e1aeSJan Lentfer conn->verify.sha1_client = NULL;
8246d49e1aeSJan Lentfer tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
8256d49e1aeSJan Lentfer TLS_ALERT_INTERNAL_ERROR);
8266d49e1aeSJan Lentfer return -1;
8276d49e1aeSJan Lentfer }
8286d49e1aeSJan Lentfer conn->verify.sha1_client = NULL;
8293ff40c12SJohn Marino hlen = MD5_MAC_LEN + SHA1_MAC_LEN;
8306d49e1aeSJan Lentfer
8313ff40c12SJohn Marino #ifdef CONFIG_TLSV12
8323ff40c12SJohn Marino }
8333ff40c12SJohn Marino #endif /* CONFIG_TLSV12 */
8343ff40c12SJohn Marino
8353ff40c12SJohn Marino if (tls_prf(conn->rl.tls_version,
8363ff40c12SJohn Marino conn->master_secret, TLS_MASTER_SECRET_LEN,
8373ff40c12SJohn Marino "client finished", hash, hlen,
8383ff40c12SJohn Marino verify_data + 1 + 3, TLS_VERIFY_DATA_LEN)) {
8396d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate verify_data");
8406d49e1aeSJan Lentfer tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
8416d49e1aeSJan Lentfer TLS_ALERT_INTERNAL_ERROR);
8426d49e1aeSJan Lentfer return -1;
8436d49e1aeSJan Lentfer }
8446d49e1aeSJan Lentfer wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (client)",
8453ff40c12SJohn Marino verify_data + 1 + 3, TLS_VERIFY_DATA_LEN);
8466d49e1aeSJan Lentfer
8476d49e1aeSJan Lentfer /* Handshake */
8483ff40c12SJohn Marino pos = hs_start = verify_data;
8496d49e1aeSJan Lentfer /* HandshakeType msg_type */
8506d49e1aeSJan Lentfer *pos++ = TLS_HANDSHAKE_TYPE_FINISHED;
8513ff40c12SJohn Marino /* uint24 length */
8523ff40c12SJohn Marino WPA_PUT_BE24(pos, TLS_VERIFY_DATA_LEN);
8536d49e1aeSJan Lentfer pos += 3;
8543ff40c12SJohn Marino pos += TLS_VERIFY_DATA_LEN; /* verify_data already in place */
8556d49e1aeSJan Lentfer tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
8566d49e1aeSJan Lentfer
8576d49e1aeSJan Lentfer if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
8583ff40c12SJohn Marino *msgpos, end - *msgpos, hs_start, pos - hs_start,
8593ff40c12SJohn Marino &rlen) < 0) {
8606d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record");
8616d49e1aeSJan Lentfer tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
8626d49e1aeSJan Lentfer TLS_ALERT_INTERNAL_ERROR);
8636d49e1aeSJan Lentfer return -1;
8646d49e1aeSJan Lentfer }
8656d49e1aeSJan Lentfer
8663ff40c12SJohn Marino *msgpos += rlen;
8676d49e1aeSJan Lentfer
8686d49e1aeSJan Lentfer return 0;
8696d49e1aeSJan Lentfer }
8706d49e1aeSJan Lentfer
8716d49e1aeSJan Lentfer
tls_send_client_key_exchange(struct tlsv1_client * conn,size_t * out_len)8726d49e1aeSJan Lentfer static u8 * tls_send_client_key_exchange(struct tlsv1_client *conn,
8736d49e1aeSJan Lentfer size_t *out_len)
8746d49e1aeSJan Lentfer {
8756d49e1aeSJan Lentfer u8 *msg, *end, *pos;
8766d49e1aeSJan Lentfer size_t msglen;
8776d49e1aeSJan Lentfer
8786d49e1aeSJan Lentfer *out_len = 0;
8796d49e1aeSJan Lentfer
8803ff40c12SJohn Marino msglen = 2000;
8816d49e1aeSJan Lentfer if (conn->certificate_requested)
8826d49e1aeSJan Lentfer msglen += tls_client_cert_chain_der_len(conn);
8836d49e1aeSJan Lentfer
8846d49e1aeSJan Lentfer msg = os_malloc(msglen);
8856d49e1aeSJan Lentfer if (msg == NULL)
8866d49e1aeSJan Lentfer return NULL;
8876d49e1aeSJan Lentfer
8886d49e1aeSJan Lentfer pos = msg;
8896d49e1aeSJan Lentfer end = msg + msglen;
8906d49e1aeSJan Lentfer
8916d49e1aeSJan Lentfer if (conn->certificate_requested) {
8926d49e1aeSJan Lentfer if (tls_write_client_certificate(conn, &pos, end) < 0) {
8936d49e1aeSJan Lentfer os_free(msg);
8946d49e1aeSJan Lentfer return NULL;
8956d49e1aeSJan Lentfer }
8966d49e1aeSJan Lentfer }
8976d49e1aeSJan Lentfer
8986d49e1aeSJan Lentfer if (tls_write_client_key_exchange(conn, &pos, end) < 0 ||
8996d49e1aeSJan Lentfer (conn->certificate_requested && conn->cred && conn->cred->key &&
9006d49e1aeSJan Lentfer tls_write_client_certificate_verify(conn, &pos, end) < 0) ||
9016d49e1aeSJan Lentfer tls_write_client_change_cipher_spec(conn, &pos, end) < 0 ||
9026d49e1aeSJan Lentfer tls_write_client_finished(conn, &pos, end) < 0) {
9036d49e1aeSJan Lentfer os_free(msg);
9046d49e1aeSJan Lentfer return NULL;
9056d49e1aeSJan Lentfer }
9066d49e1aeSJan Lentfer
9076d49e1aeSJan Lentfer *out_len = pos - msg;
9086d49e1aeSJan Lentfer
9096d49e1aeSJan Lentfer conn->state = SERVER_CHANGE_CIPHER_SPEC;
9106d49e1aeSJan Lentfer
9116d49e1aeSJan Lentfer return msg;
9126d49e1aeSJan Lentfer }
9136d49e1aeSJan Lentfer
9146d49e1aeSJan Lentfer
tls_send_change_cipher_spec(struct tlsv1_client * conn,size_t * out_len)9156d49e1aeSJan Lentfer static u8 * tls_send_change_cipher_spec(struct tlsv1_client *conn,
9166d49e1aeSJan Lentfer size_t *out_len)
9176d49e1aeSJan Lentfer {
9186d49e1aeSJan Lentfer u8 *msg, *end, *pos;
9196d49e1aeSJan Lentfer
9206d49e1aeSJan Lentfer *out_len = 0;
9216d49e1aeSJan Lentfer
9226d49e1aeSJan Lentfer msg = os_malloc(1000);
9236d49e1aeSJan Lentfer if (msg == NULL)
9246d49e1aeSJan Lentfer return NULL;
9256d49e1aeSJan Lentfer
9266d49e1aeSJan Lentfer pos = msg;
9276d49e1aeSJan Lentfer end = msg + 1000;
9286d49e1aeSJan Lentfer
9296d49e1aeSJan Lentfer if (tls_write_client_change_cipher_spec(conn, &pos, end) < 0 ||
9306d49e1aeSJan Lentfer tls_write_client_finished(conn, &pos, end) < 0) {
9316d49e1aeSJan Lentfer os_free(msg);
9326d49e1aeSJan Lentfer return NULL;
9336d49e1aeSJan Lentfer }
9346d49e1aeSJan Lentfer
9356d49e1aeSJan Lentfer *out_len = pos - msg;
9366d49e1aeSJan Lentfer
9376d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "TLSv1: Session resumption completed "
9386d49e1aeSJan Lentfer "successfully");
939*a1157835SDaniel Fojt if (!conn->session_resumed && conn->use_session_ticket)
940*a1157835SDaniel Fojt conn->session_resumed = 1;
9416d49e1aeSJan Lentfer conn->state = ESTABLISHED;
9426d49e1aeSJan Lentfer
9436d49e1aeSJan Lentfer return msg;
9446d49e1aeSJan Lentfer }
9456d49e1aeSJan Lentfer
9466d49e1aeSJan Lentfer
tlsv1_client_handshake_write(struct tlsv1_client * conn,size_t * out_len,int no_appl_data)9476d49e1aeSJan Lentfer u8 * tlsv1_client_handshake_write(struct tlsv1_client *conn, size_t *out_len,
9486d49e1aeSJan Lentfer int no_appl_data)
9496d49e1aeSJan Lentfer {
9506d49e1aeSJan Lentfer switch (conn->state) {
9516d49e1aeSJan Lentfer case CLIENT_KEY_EXCHANGE:
9526d49e1aeSJan Lentfer return tls_send_client_key_exchange(conn, out_len);
9536d49e1aeSJan Lentfer case CHANGE_CIPHER_SPEC:
9546d49e1aeSJan Lentfer return tls_send_change_cipher_spec(conn, out_len);
9556d49e1aeSJan Lentfer case ACK_FINISHED:
9566d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "TLSv1: Handshake completed "
9576d49e1aeSJan Lentfer "successfully");
9586d49e1aeSJan Lentfer conn->state = ESTABLISHED;
9596d49e1aeSJan Lentfer *out_len = 0;
9606d49e1aeSJan Lentfer if (no_appl_data) {
9616d49e1aeSJan Lentfer /* Need to return something to get final TLS ACK. */
9626d49e1aeSJan Lentfer return os_malloc(1);
9636d49e1aeSJan Lentfer }
9646d49e1aeSJan Lentfer return NULL;
9656d49e1aeSJan Lentfer default:
9666d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d while "
9676d49e1aeSJan Lentfer "generating reply", conn->state);
9686d49e1aeSJan Lentfer return NULL;
9696d49e1aeSJan Lentfer }
9706d49e1aeSJan Lentfer }
9716d49e1aeSJan Lentfer
9726d49e1aeSJan Lentfer
tlsv1_client_send_alert(struct tlsv1_client * conn,u8 level,u8 description,size_t * out_len)9736d49e1aeSJan Lentfer u8 * tlsv1_client_send_alert(struct tlsv1_client *conn, u8 level,
9746d49e1aeSJan Lentfer u8 description, size_t *out_len)
9756d49e1aeSJan Lentfer {
9766d49e1aeSJan Lentfer u8 *alert, *pos, *length;
9776d49e1aeSJan Lentfer
9786d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "TLSv1: Send Alert(%d:%d)", level, description);
9796d49e1aeSJan Lentfer *out_len = 0;
9806d49e1aeSJan Lentfer
9816d49e1aeSJan Lentfer alert = os_malloc(10);
9826d49e1aeSJan Lentfer if (alert == NULL)
9836d49e1aeSJan Lentfer return NULL;
9846d49e1aeSJan Lentfer
9856d49e1aeSJan Lentfer pos = alert;
9866d49e1aeSJan Lentfer
9876d49e1aeSJan Lentfer /* TLSPlaintext */
9886d49e1aeSJan Lentfer /* ContentType type */
9896d49e1aeSJan Lentfer *pos++ = TLS_CONTENT_TYPE_ALERT;
9906d49e1aeSJan Lentfer /* ProtocolVersion version */
9913ff40c12SJohn Marino WPA_PUT_BE16(pos, conn->rl.tls_version ? conn->rl.tls_version :
9923ff40c12SJohn Marino TLS_VERSION);
9936d49e1aeSJan Lentfer pos += 2;
9946d49e1aeSJan Lentfer /* uint16 length (to be filled) */
9956d49e1aeSJan Lentfer length = pos;
9966d49e1aeSJan Lentfer pos += 2;
9976d49e1aeSJan Lentfer /* opaque fragment[TLSPlaintext.length] */
9986d49e1aeSJan Lentfer
9996d49e1aeSJan Lentfer /* Alert */
10006d49e1aeSJan Lentfer /* AlertLevel level */
10016d49e1aeSJan Lentfer *pos++ = level;
10026d49e1aeSJan Lentfer /* AlertDescription description */
10036d49e1aeSJan Lentfer *pos++ = description;
10046d49e1aeSJan Lentfer
10056d49e1aeSJan Lentfer WPA_PUT_BE16(length, pos - length - 2);
10066d49e1aeSJan Lentfer *out_len = pos - alert;
10076d49e1aeSJan Lentfer
10086d49e1aeSJan Lentfer return alert;
10096d49e1aeSJan Lentfer }
1010