1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// found in the LICENSE file.
4cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/ssl/openssl_ssl_util.h"
65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <errno.h>
8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <openssl/err.h>
10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <openssl/ssl.h>
11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/bind.h"
13116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/lazy_instance.h"
14116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/location.h"
15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/logging.h"
161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/values.h"
17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "crypto/openssl_util.h"
18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "net/base/net_errors.h"
19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace net {
21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)SslSetClearMask::SslSetClearMask()
23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    : set_mask(0),
24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      clear_mask(0) {
25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void SslSetClearMask::ConfigureFlag(long flag, bool state) {
28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  (state ? set_mask : clear_mask) |= flag;
29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Make sure we haven't got any intersection in the set & clear options.
30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK_EQ(0, set_mask & clear_mask) << flag << ":" << state;
31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace {
34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
35116680a4aac90f2aa7413d9095a592090648e557Ben Murdochclass OpenSSLNetErrorLibSingleton {
36116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch public:
37116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  OpenSSLNetErrorLibSingleton() {
38116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    crypto::EnsureOpenSSLInit();
39116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
40116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // Allocate a new error library value for inserting net errors into
41116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // OpenSSL. This does not register any ERR_STRING_DATA for the errors, so
42116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // stringifying error codes through OpenSSL will return NULL.
43116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    net_error_lib_ = ERR_get_next_error_library();
44116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
45116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  unsigned net_error_lib() const { return net_error_lib_; }
47116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
48116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch private:
495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  unsigned net_error_lib_;
50116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch};
51116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
52116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbase::LazyInstance<OpenSSLNetErrorLibSingleton>::Leaky g_openssl_net_error_lib =
53116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    LAZY_INSTANCE_INITIALIZER;
54116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)unsigned OpenSSLNetErrorLib() {
56116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return g_openssl_net_error_lib.Get().net_error_lib();
57116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
58116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciint MapOpenSSLErrorSSL(uint32_t error_code) {
60116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_EQ(ERR_LIB_SSL, ERR_GET_LIB(error_code));
61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DVLOG(1) << "OpenSSL SSL error, reason: " << ERR_GET_REASON(error_code)
63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)           << ", name: " << ERR_error_string(error_code, NULL);
64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  switch (ERR_GET_REASON(error_code)) {
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_READ_TIMEOUT_EXPIRED:
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return ERR_TIMED_OUT;
67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_UNKNOWN_CERTIFICATE_TYPE:
68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_UNKNOWN_CIPHER_TYPE:
69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE:
70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_UNKNOWN_PKEY_TYPE:
71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_UNKNOWN_SSL_VERSION:
72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return ERR_NOT_IMPLEMENTED;
73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_UNSUPPORTED_SSL_VERSION:
74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_NO_CIPHER_MATCH:
75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_NO_SHARED_CIPHER:
76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY:
77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_TLSV1_ALERT_PROTOCOL_VERSION:
78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_UNSUPPORTED_PROTOCOL:
79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return ERR_SSL_VERSION_OR_CIPHER_MISMATCH;
80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_SSLV3_ALERT_BAD_CERTIFICATE:
81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE:
82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED:
83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED:
84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN:
85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_TLSV1_ALERT_ACCESS_DENIED:
86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_TLSV1_ALERT_UNKNOWN_CA:
87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return ERR_BAD_SSL_CLIENT_AUTH_CERT;
88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE:
89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return ERR_SSL_DECOMPRESSION_FAILURE_ALERT;
90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_SSLV3_ALERT_BAD_RECORD_MAC:
91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return ERR_SSL_BAD_RECORD_MAC_ALERT;
92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_TLSV1_ALERT_DECRYPT_ERROR:
93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return ERR_SSL_DECRYPT_ERROR_ALERT;
94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_TLSV1_UNRECOGNIZED_NAME:
95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return ERR_SSL_UNRECOGNIZED_NAME_ALERT;
96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED:
97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return ERR_SSL_UNSAFE_NEGOTIATION;
9803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    case SSL_R_BAD_DH_P_LENGTH:
99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY;
100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // SSL_R_UNKNOWN_PROTOCOL is reported if premature application data is
101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // received (see http://crbug.com/42538), and also if all the protocol
102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // versions supported by the server were disabled in this socket instance.
103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Mapped to ERR_SSL_PROTOCOL_ERROR for compatibility with other SSL sockets
104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // in the former scenario.
105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_UNKNOWN_PROTOCOL:
106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_SSL_HANDSHAKE_FAILURE:
107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_DECRYPTION_FAILED:
108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC:
109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG:
110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_DIGEST_CHECK_FAILED:
111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_ENCRYPTED_LENGTH_TOO_LONG:
112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST:
113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_EXCESSIVE_MESSAGE_SIZE:
114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_EXTRA_DATA_IN_MESSAGE:
115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_GOT_A_FIN_BEFORE_A_CCS:
116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_INVALID_COMMAND:
117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_INVALID_STATUS_RESPONSE:
118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_INVALID_TICKET_KEYS_LENGTH:
119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // SSL_do_handshake reports this error when the server responds to a
120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // ClientHello with a fatal close_notify alert.
121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_AD_REASON_OFFSET + SSL_AD_CLOSE_NOTIFY:
122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE:
123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // TODO(joth): SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE may be returned from the
124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // server after receiving ClientHello if there's no common supported cipher.
125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Ideally we'd map that specific case to ERR_SSL_VERSION_OR_CIPHER_MISMATCH
126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // to match the NSS implementation. See also http://goo.gl/oMtZW
127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE:
128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_SSLV3_ALERT_NO_CERTIFICATE:
129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER:
130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_TLSV1_ALERT_DECODE_ERROR:
131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_TLSV1_ALERT_DECRYPTION_FAILED:
132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION:
133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_TLSV1_ALERT_INTERNAL_ERROR:
134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_TLSV1_ALERT_NO_RENEGOTIATION:
135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_TLSV1_ALERT_RECORD_OVERFLOW:
136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_TLSV1_ALERT_USER_CANCELLED:
137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return ERR_SSL_PROTOCOL_ERROR;
138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_R_CERTIFICATE_VERIFY_FAILED:
139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // The only way that the certificate verify callback can fail is if
140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // the leaf certificate changed during a renegotiation.
141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return ERR_SSL_SERVER_CERT_CHANGED;
1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    case SSL_AD_REASON_OFFSET + SSL3_AD_INAPPROPRIATE_FALLBACK:
1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      return ERR_SSL_INAPPROPRIATE_FALLBACK;
144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    default:
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      LOG(WARNING) << "Unmapped error reason: " << ERR_GET_REASON(error_code);
1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return ERR_SSL_PROTOCOL_ERROR;
147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibase::Value* NetLogOpenSSLErrorCallback(int net_error,
1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                        int ssl_error,
1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                        const OpenSSLErrorInfo& error_info,
1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                        NetLog::LogLevel /* log_level */) {
1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::DictionaryValue* dict = new base::DictionaryValue();
1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  dict->SetInteger("net_error", net_error);
1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  dict->SetInteger("ssl_error", ssl_error);
1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (error_info.error_code != 0) {
1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    dict->SetInteger("error_lib", ERR_GET_LIB(error_info.error_code));
1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    dict->SetInteger("error_reason", ERR_GET_REASON(error_info.error_code));
1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (error_info.file != NULL)
1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    dict->SetString("file", error_info.file);
1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (error_info.line != 0)
1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    dict->SetInteger("line", error_info.line);
1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return dict;
1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}  // namespace
169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
170116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid OpenSSLPutNetError(const tracked_objects::Location& location, int err) {
171116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Net error codes are negative. Encode them as positive numbers.
172116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  err = -err;
173116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (err < 0 || err > 0xfff) {
174116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // OpenSSL reserves 12 bits for the reason code.
175116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    NOTREACHED();
176116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    err = ERR_INVALID_ARGUMENT;
177116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ERR_put_error(OpenSSLNetErrorLib(), 0, err,
179116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                location.file_name(), location.line_number());
180116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
181116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int MapOpenSSLError(int err, const crypto::OpenSSLErrStackTracer& tracer) {
1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  OpenSSLErrorInfo error_info;
1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return MapOpenSSLErrorWithDetails(err, tracer, &error_info);
1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciint MapOpenSSLErrorWithDetails(int err,
1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               const crypto::OpenSSLErrStackTracer& tracer,
1891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               OpenSSLErrorInfo* out_error_info) {
1901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  *out_error_info = OpenSSLErrorInfo();
1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  switch (err) {
193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_ERROR_WANT_READ:
194cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_ERROR_WANT_WRITE:
195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return ERR_IO_PENDING;
196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_ERROR_SYSCALL:
197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      LOG(ERROR) << "OpenSSL SYSCALL error, earliest error code in "
198cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                    "error queue: " << ERR_peek_error() << ", errno: "
199cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 << errno;
2001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return ERR_FAILED;
201cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SSL_ERROR_SSL:
202116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      // Walk down the error stack to find an SSL or net error.
2031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      uint32_t error_code;
2041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      const char* file;
2051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      int line;
206116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      do {
2071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        error_code = ERR_get_error_line(&file, &line);
208116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        if (ERR_GET_LIB(error_code) == ERR_LIB_SSL) {
2091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          out_error_info->error_code = error_code;
2101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          out_error_info->file = file;
2111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          out_error_info->line = line;
212116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          return MapOpenSSLErrorSSL(error_code);
213116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        } else if (ERR_GET_LIB(error_code) == OpenSSLNetErrorLib()) {
2141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          out_error_info->error_code = error_code;
2151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          out_error_info->file = file;
2161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          out_error_info->line = line;
217116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          // Net error codes are negative but encoded in OpenSSL as positive
218116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          // numbers.
219116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          return -ERR_GET_REASON(error_code);
220116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        }
221116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      } while (error_code != 0);
2221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return ERR_FAILED;
223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    default:
224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // TODO(joth): Implement full mapping.
225cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      LOG(WARNING) << "Unknown OpenSSL error " << err;
226cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return ERR_SSL_PROTOCOL_ERROR;
227cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
229cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
2301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciNetLog::ParametersCallback CreateNetLogOpenSSLErrorCallback(
2311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    int net_error,
2321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    int ssl_error,
2331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const OpenSSLErrorInfo& error_info) {
2341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return base::Bind(&NetLogOpenSSLErrorCallback,
2351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    net_error, ssl_error, error_info);
2361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
2371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
238cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}  // namespace net
239