Upstream version 9.37.197.0
[platform/framework/web/crosswalk.git] / src / net / socket / openssl_ssl_util.cc
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/socket/openssl_ssl_util.h"
6
7 #include <openssl/err.h>
8 #include <openssl/ssl.h>
9
10 #include "base/logging.h"
11 #include "crypto/openssl_util.h"
12 #include "net/base/net_errors.h"
13
14 namespace net {
15
16 SslSetClearMask::SslSetClearMask()
17     : set_mask(0),
18       clear_mask(0) {
19 }
20
21 void SslSetClearMask::ConfigureFlag(long flag, bool state) {
22   (state ? set_mask : clear_mask) |= flag;
23   // Make sure we haven't got any intersection in the set & clear options.
24   DCHECK_EQ(0, set_mask & clear_mask) << flag << ":" << state;
25 }
26
27 namespace {
28
29 int MapOpenSSLErrorSSL() {
30   // Walk down the error stack to find the SSLerr generated reason.
31   unsigned long error_code;
32   do {
33     error_code = ERR_get_error();
34     if (error_code == 0)
35       return ERR_SSL_PROTOCOL_ERROR;
36   } while (ERR_GET_LIB(error_code) != ERR_LIB_SSL);
37
38   DVLOG(1) << "OpenSSL SSL error, reason: " << ERR_GET_REASON(error_code)
39            << ", name: " << ERR_error_string(error_code, NULL);
40   switch (ERR_GET_REASON(error_code)) {
41     case SSL_R_READ_TIMEOUT_EXPIRED:
42       return ERR_TIMED_OUT;
43     case SSL_R_BAD_RESPONSE_ARGUMENT:
44       return ERR_INVALID_ARGUMENT;
45     case SSL_R_UNKNOWN_CERTIFICATE_TYPE:
46     case SSL_R_UNKNOWN_CIPHER_TYPE:
47     case SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE:
48     case SSL_R_UNKNOWN_PKEY_TYPE:
49     case SSL_R_UNKNOWN_REMOTE_ERROR_TYPE:
50     case SSL_R_UNKNOWN_SSL_VERSION:
51       return ERR_NOT_IMPLEMENTED;
52     case SSL_R_UNSUPPORTED_SSL_VERSION:
53     case SSL_R_NO_CIPHER_MATCH:
54     case SSL_R_NO_SHARED_CIPHER:
55     case SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY:
56     case SSL_R_TLSV1_ALERT_PROTOCOL_VERSION:
57     case SSL_R_UNSUPPORTED_PROTOCOL:
58       return ERR_SSL_VERSION_OR_CIPHER_MISMATCH;
59     case SSL_R_SSLV3_ALERT_BAD_CERTIFICATE:
60     case SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE:
61     case SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED:
62     case SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED:
63     case SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN:
64     case SSL_R_TLSV1_ALERT_ACCESS_DENIED:
65     case SSL_R_TLSV1_ALERT_UNKNOWN_CA:
66       return ERR_BAD_SSL_CLIENT_AUTH_CERT;
67     case SSL_R_BAD_DECOMPRESSION:
68     case SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE:
69       return ERR_SSL_DECOMPRESSION_FAILURE_ALERT;
70     case SSL_R_SSLV3_ALERT_BAD_RECORD_MAC:
71       return ERR_SSL_BAD_RECORD_MAC_ALERT;
72     case SSL_R_TLSV1_ALERT_DECRYPT_ERROR:
73       return ERR_SSL_DECRYPT_ERROR_ALERT;
74     case SSL_R_TLSV1_UNRECOGNIZED_NAME:
75       return ERR_SSL_UNRECOGNIZED_NAME_ALERT;
76     case SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED:
77       return ERR_SSL_UNSAFE_NEGOTIATION;
78     case SSL_R_WRONG_NUMBER_OF_KEY_BITS:
79       return ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY;
80     // SSL_R_UNKNOWN_PROTOCOL is reported if premature application data is
81     // received (see http://crbug.com/42538), and also if all the protocol
82     // versions supported by the server were disabled in this socket instance.
83     // Mapped to ERR_SSL_PROTOCOL_ERROR for compatibility with other SSL sockets
84     // in the former scenario.
85     case SSL_R_UNKNOWN_PROTOCOL:
86     case SSL_R_SSL_HANDSHAKE_FAILURE:
87     case SSL_R_DECRYPTION_FAILED:
88     case SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC:
89     case SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG:
90     case SSL_R_DIGEST_CHECK_FAILED:
91     case SSL_R_DUPLICATE_COMPRESSION_ID:
92     case SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER:
93     case SSL_R_ENCRYPTED_LENGTH_TOO_LONG:
94     case SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST:
95     case SSL_R_EXCESSIVE_MESSAGE_SIZE:
96     case SSL_R_EXTRA_DATA_IN_MESSAGE:
97     case SSL_R_GOT_A_FIN_BEFORE_A_CCS:
98     case SSL_R_ILLEGAL_PADDING:
99     case SSL_R_INVALID_CHALLENGE_LENGTH:
100     case SSL_R_INVALID_COMMAND:
101     case SSL_R_INVALID_PURPOSE:
102     case SSL_R_INVALID_STATUS_RESPONSE:
103     case SSL_R_INVALID_TICKET_KEYS_LENGTH:
104     case SSL_R_KEY_ARG_TOO_LONG:
105     case SSL_R_READ_WRONG_PACKET_TYPE:
106     // SSL_do_handshake reports this error when the server responds to a
107     // ClientHello with a fatal close_notify alert.
108     case SSL_AD_REASON_OFFSET + SSL_AD_CLOSE_NOTIFY:
109     case SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE:
110     // TODO(joth): SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE may be returned from the
111     // server after receiving ClientHello if there's no common supported cipher.
112     // Ideally we'd map that specific case to ERR_SSL_VERSION_OR_CIPHER_MISMATCH
113     // to match the NSS implementation. See also http://goo.gl/oMtZW
114     case SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE:
115     case SSL_R_SSLV3_ALERT_NO_CERTIFICATE:
116     case SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER:
117     case SSL_R_TLSV1_ALERT_DECODE_ERROR:
118     case SSL_R_TLSV1_ALERT_DECRYPTION_FAILED:
119     case SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION:
120     case SSL_R_TLSV1_ALERT_INTERNAL_ERROR:
121     case SSL_R_TLSV1_ALERT_NO_RENEGOTIATION:
122     case SSL_R_TLSV1_ALERT_RECORD_OVERFLOW:
123     case SSL_R_TLSV1_ALERT_USER_CANCELLED:
124       return ERR_SSL_PROTOCOL_ERROR;
125     case SSL_R_CERTIFICATE_VERIFY_FAILED:
126       // The only way that the certificate verify callback can fail is if
127       // the leaf certificate changed during a renegotiation.
128       return ERR_SSL_SERVER_CERT_CHANGED;
129     default:
130       LOG(WARNING) << "Unmapped error reason: " << ERR_GET_REASON(error_code);
131       return ERR_FAILED;
132   }
133 }
134
135 }  // namespace
136
137 int MapOpenSSLError(int err, const crypto::OpenSSLErrStackTracer& tracer) {
138   switch (err) {
139     case SSL_ERROR_WANT_READ:
140     case SSL_ERROR_WANT_WRITE:
141       return ERR_IO_PENDING;
142     case SSL_ERROR_SYSCALL:
143       LOG(ERROR) << "OpenSSL SYSCALL error, earliest error code in "
144                     "error queue: " << ERR_peek_error() << ", errno: "
145                  << errno;
146       return ERR_SSL_PROTOCOL_ERROR;
147     case SSL_ERROR_SSL:
148       return MapOpenSSLErrorSSL();
149     default:
150       // TODO(joth): Implement full mapping.
151       LOG(WARNING) << "Unknown OpenSSL error " << err;
152       return ERR_SSL_PROTOCOL_ERROR;
153   }
154 }
155
156 }  // namespace net