summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--devtools/client/locales/en-US/netmonitor.properties31
-rw-r--r--devtools/client/netmonitor/netmonitor-view.js2
-rw-r--r--devtools/client/netmonitor/netmonitor.xul20
-rw-r--r--devtools/client/netmonitor/test/browser_net_security-details.js4
-rw-r--r--devtools/shared/webconsole/network-helper.js27
-rw-r--r--security/manager/ssl/nsISSLStatus.idl4
-rw-r--r--security/manager/ssl/nsNSSCallbacks.cpp96
-rw-r--r--security/manager/ssl/nsNSSIOLayer.cpp4
-rw-r--r--security/manager/ssl/nsSSLStatus.cpp42
-rw-r--r--security/manager/ssl/nsSSLStatus.h2
-rw-r--r--testing/web-platform/meta/navigation-timing/idlharness.html.ini6
-rw-r--r--toolkit/components/telemetry/Histograms.json31
-rw-r--r--toolkit/components/telemetry/histogram-whitelists.json4
13 files changed, 258 insertions, 15 deletions
diff --git a/devtools/client/locales/en-US/netmonitor.properties b/devtools/client/locales/en-US/netmonitor.properties
index f07f38907c..1f6f671c91 100644
--- a/devtools/client/locales/en-US/netmonitor.properties
+++ b/devtools/client/locales/en-US/netmonitor.properties
@@ -617,6 +617,37 @@ netmonitor.security.protocolVersion=Protocol version:
# in the security tab describing the cipher suite used to secure this connection.
netmonitor.security.cipherSuite=Cipher suite:
+# LOCALIZATION NOTE (netmonitor.security.keaGroup): This is the label displayed
+# in the security tab describing the key exchange group suite used to secure
+# this connection.
+netmonitor.security.keaGroup=Key Exchange Group:
+
+# LOCALIZATION NOTE (netmonitor.security.keaGroup.none): This is the label
+# displayed in the security tab describing the case when no group was used.
+netmonitor.security.keaGroup.none=none
+
+# LOCALIZATION NOTE (netmonitor.security.keaGroup.custom): This is the label
+# displayed in the security tab describing the case when a custom group was used.
+netmonitor.security.keaGroup.custom=custom
+
+# LOCALIZATION NOTE (netmonitor.security.keaGroup.unknown): This is the value
+# displayed in the security tab describing an unknown group.
+netmonitor.security.keaGroup.unknown=unknown group
+
+# LOCALIZATION NOTE (netmonitor.security.signatureScheme): This is the label
+# displayed in the security tab describing the signature scheme used by for
+# the server certificate in this connection.
+netmonitor.security.signatureScheme=Signature Scheme:
+
+# LOCALIZATION NOTE (netmonitor.security.signatureScheme.none): This is the
+# label displayed in the security tab describing the case when no signature
+# was used.
+netmonitor.security.signatureScheme.none=none
+
+# LOCALIZATION NOTE (netmonitor.security.signatureScheme.unknown): This is the
+# value displayed in the security tab describing an unknown signature scheme.
+netmonitor.security.signatureScheme.unknown=unknown signature scheme
+
# LOCALIZATION NOTE (netmonitor.security.hsts): This is the label displayed
# in the security tab describing the usage of HTTP Strict Transport Security.
netmonitor.security.hsts=HTTP Strict Transport Security:
diff --git a/devtools/client/netmonitor/netmonitor-view.js b/devtools/client/netmonitor/netmonitor-view.js
index 1f957db1bb..19dd96ff1a 100644
--- a/devtools/client/netmonitor/netmonitor-view.js
+++ b/devtools/client/netmonitor/netmonitor-view.js
@@ -1124,6 +1124,8 @@ NetworkDetailsView.prototype = {
setValue("#security-protocol-version-value",
securityInfo.protocolVersion);
setValue("#security-ciphersuite-value", securityInfo.cipherSuite);
+ setValue("#security-keagroup-value", securityInfo.keaGroupName);
+ setValue("#security-signaturescheme-value", securityInfo.signatureSchemeName);
// Host header
let domain = getUriHostPort(url);
diff --git a/devtools/client/netmonitor/netmonitor.xul b/devtools/client/netmonitor/netmonitor.xul
index 8a0c603890..117ecf2614 100644
--- a/devtools/client/netmonitor/netmonitor.xul
+++ b/devtools/client/netmonitor/netmonitor.xul
@@ -550,6 +550,26 @@
id="security-warning-cipher"
data-localization="tooltiptext=netmonitor.security.warning.cipher" />
</hbox>
+ <hbox id="security-keagroup"
+ class="tabpanel-summary-container"
+ align="baseline">
+ <label class="plain tabpanel-summary-label"
+ data-localization="content=netmonitor.security.keaGroup"/>
+ <textbox id="security-keagroup-value"
+ class="plain tabpanel-summary-value devtools-monospace cropped-textbox"
+ flex="1"
+ readonly="true"/>
+ </hbox>
+ <hbox id="security-signaturescheme"
+ class="tabpanel-summary-container"
+ align="baseline">
+ <label class="plain tabpanel-summary-label"
+ data-localization="content=netmonitor.security.signatureScheme"/>
+ <textbox id="security-signaturescheme-value"
+ class="plain tabpanel-summary-value devtools-monospace cropped-textbox"
+ flex="1"
+ readonly="true"/>
+ </hbox>
</vbox>
</vbox>
<vbox id="security-info-domain"
diff --git a/devtools/client/netmonitor/test/browser_net_security-details.js b/devtools/client/netmonitor/test/browser_net_security-details.js
index 0a83b3ed9f..61f39a414e 100644
--- a/devtools/client/netmonitor/test/browser_net_security-details.js
+++ b/devtools/client/netmonitor/test/browser_net_security-details.js
@@ -66,6 +66,10 @@ add_task(function* () {
checkLabel("#security-cert-issuer-o", "Mozilla Testing");
checkLabel("#security-cert-issuer-ou", "<Not Available>");
+ // These two values can change. So only check they're not empty.
+ checkLabelNotEmpty("#security-keagroup-value");
+ checkLabelNotEmpty("#security-signaturescheme-value");
+
// Locale sensitive and varies between timezones. Cant't compare equality or
// the test fails depending on which part of the world the test is executed.
checkLabelNotEmpty("#security-cert-validity-begins");
diff --git a/devtools/shared/webconsole/network-helper.js b/devtools/shared/webconsole/network-helper.js
index af6a2e55b3..4e25fac260 100644
--- a/devtools/shared/webconsole/network-helper.js
+++ b/devtools/shared/webconsole/network-helper.js
@@ -63,6 +63,8 @@ const {components, Cc, Ci} = require("chrome");
loader.lazyImporter(this, "NetUtil", "resource://gre/modules/NetUtil.jsm");
const DevToolsUtils = require("devtools/shared/DevToolsUtils");
const Services = require("Services");
+const { LocalizationHelper } = require("devtools/shared/l10n");
+const L10N = new LocalizationHelper("devtools/client/locales/netmonitor.properties");
// The cache used in the `nsIURL` function.
const gNSURLStore = new Map();
@@ -620,6 +622,31 @@ var NetworkHelper = {
// Cipher suite.
info.cipherSuite = SSLStatus.cipherName;
+ // Key exchange group name.
+ info.keaGroupName = SSLStatus.keaGroupName;
+ // Localise two special values.
+ if (info.keaGroupName == "none") {
+ info.keaGroupName = L10N.getStr("netmonitor.security.keaGroup.none");
+ }
+ if (info.keaGroupName == "custom") {
+ info.keaGroupName = L10N.getStr("netmonitor.security.keaGroup.custom");
+ }
+ if (info.keaGroupName == "unknown group") {
+ info.keaGroupName = L10N.getStr("netmonitor.security.keaGroup.unknown");
+ }
+
+ // Certificate signature scheme.
+ info.signatureSchemeName = SSLStatus.signatureSchemeName;
+ // Localise two special values.
+ if (info.signatureSchemeName == "none") {
+ info.signatureSchemeName =
+ L10N.getStr("netmonitor.security.signatureScheme.none");
+ }
+ if (info.signatureSchemeName == "unknown signature") {
+ info.signatureSchemeName =
+ L10N.getStr("netmonitor.security.signatureScheme.unknown");
+ }
+
// Protocol version.
info.protocolVersion =
this.formatSecurityProtocol(SSLStatus.protocolVersion);
diff --git a/security/manager/ssl/nsISSLStatus.idl b/security/manager/ssl/nsISSLStatus.idl
index f5c56a8cf8..52cb1df30a 100644
--- a/security/manager/ssl/nsISSLStatus.idl
+++ b/security/manager/ssl/nsISSLStatus.idl
@@ -15,6 +15,10 @@ interface nsISSLStatus : nsISupports {
readonly attribute ACString cipherName;
readonly attribute unsigned long keyLength;
readonly attribute unsigned long secretKeyLength;
+ [must_use]
+ readonly attribute ACString keaGroupName;
+ [must_use]
+ readonly attribute ACString signatureSchemeName;
const short SSL_VERSION_3 = 0;
const short TLS_VERSION_1 = 1;
diff --git a/security/manager/ssl/nsNSSCallbacks.cpp b/security/manager/ssl/nsNSSCallbacks.cpp
index e28760d5f9..9411012651 100644
--- a/security/manager/ssl/nsNSSCallbacks.cpp
+++ b/security/manager/ssl/nsNSSCallbacks.cpp
@@ -848,6 +848,99 @@ PK11PasswordPrompt(PK11SlotInfo* slot, PRBool /*retry*/, void* arg)
return runnable->mResult;
}
+static nsCString
+getKeaGroupName(uint32_t aKeaGroup)
+{
+ nsCString groupName;
+ switch (aKeaGroup) {
+ case ssl_grp_ec_secp256r1:
+ groupName = NS_LITERAL_CSTRING("P256");
+ break;
+ case ssl_grp_ec_secp384r1:
+ groupName = NS_LITERAL_CSTRING("P384");
+ break;
+ case ssl_grp_ec_secp521r1:
+ groupName = NS_LITERAL_CSTRING("P521");
+ break;
+ case ssl_grp_ec_curve25519:
+ groupName = NS_LITERAL_CSTRING("x25519");
+ break;
+ case ssl_grp_ffdhe_2048:
+ groupName = NS_LITERAL_CSTRING("FF 2048");
+ break;
+ case ssl_grp_ffdhe_3072:
+ groupName = NS_LITERAL_CSTRING("FF 3072");
+ break;
+ case ssl_grp_none:
+ groupName = NS_LITERAL_CSTRING("none");
+ break;
+ case ssl_grp_ffdhe_custom:
+ groupName = NS_LITERAL_CSTRING("custom");
+ break;
+ // All other groups are not enabled in Firefox. See namedGroups in
+ // nsNSSIOLayer.cpp.
+ default:
+ // This really shouldn't happen!
+ MOZ_ASSERT_UNREACHABLE("Invalid key exchange group.");
+ groupName = NS_LITERAL_CSTRING("unknown group");
+ }
+ return groupName;
+}
+
+static nsCString
+getSignatureName(uint32_t aSignatureScheme)
+{
+ nsCString signatureName;
+ switch (aSignatureScheme) {
+ case ssl_sig_none:
+ signatureName = NS_LITERAL_CSTRING("none");
+ break;
+ case ssl_sig_rsa_pkcs1_sha1:
+ signatureName = NS_LITERAL_CSTRING("RSA-PKCS1-SHA1");
+ break;
+ case ssl_sig_rsa_pkcs1_sha256:
+ signatureName = NS_LITERAL_CSTRING("RSA-PKCS1-SHA256");
+ break;
+ case ssl_sig_rsa_pkcs1_sha384:
+ signatureName = NS_LITERAL_CSTRING("RSA-PKCS1-SHA384");
+ break;
+ case ssl_sig_rsa_pkcs1_sha512:
+ signatureName = NS_LITERAL_CSTRING("RSA-PKCS1-SHA512");
+ break;
+ case ssl_sig_ecdsa_secp256r1_sha256:
+ signatureName = NS_LITERAL_CSTRING("ECDSA-P256-SHA256");
+ break;
+ case ssl_sig_ecdsa_secp384r1_sha384:
+ signatureName = NS_LITERAL_CSTRING("ECDSA-P384-SHA384");
+ break;
+ case ssl_sig_ecdsa_secp521r1_sha512:
+ signatureName = NS_LITERAL_CSTRING("ECDSA-P521-SHA512");
+ break;
+ case ssl_sig_rsa_pss_sha256:
+ signatureName = NS_LITERAL_CSTRING("RSA-PSS-SHA256");
+ break;
+ case ssl_sig_rsa_pss_sha384:
+ signatureName = NS_LITERAL_CSTRING("RSA-PSS-SHA384");
+ break;
+ case ssl_sig_rsa_pss_sha512:
+ signatureName = NS_LITERAL_CSTRING("RSA-PSS-SHA512");
+ break;
+ case ssl_sig_ecdsa_sha1:
+ signatureName = NS_LITERAL_CSTRING("ECDSA-SHA1");
+ break;
+ case ssl_sig_rsa_pkcs1_sha1md5:
+ signatureName = NS_LITERAL_CSTRING("RSA-PKCS1-SHA1MD5");
+ break;
+ // All other groups are not enabled in Firefox. See sEnabledSignatureSchemes
+ // in nsNSSIOLayer.cpp.
+ default:
+ // This really shouldn't happen!
+ MOZ_ASSERT_UNREACHABLE("Invalid signature scheme.");
+ signatureName = NS_LITERAL_CSTRING("unknown signature");
+ }
+ return signatureName;
+}
+
// call with shutdown prevention lock held
static void
PreliminaryHandshakeDone(PRFileDesc* fd)
@@ -874,6 +967,9 @@ PreliminaryHandshakeDone(PRFileDesc* fd)
status->mHaveCipherSuiteAndProtocol = true;
status->mCipherSuite = channelInfo.cipherSuite;
status->mProtocolVersion = channelInfo.protocolVersion & 0xFF;
+ status->mKeaGroup.Assign(getKeaGroupName(channelInfo.keaGroup));
+ status->mSignatureSchemeName.Assign(
+ getSignatureName(channelInfo.signatureScheme));
infoObject->SetKEAUsed(channelInfo.keaType);
infoObject->SetKEAKeyBits(channelInfo.keaKeyBits);
infoObject->SetMACAlgorithmUsed(cipherInfo.macAlgorithm);
diff --git a/security/manager/ssl/nsNSSIOLayer.cpp b/security/manager/ssl/nsNSSIOLayer.cpp
index 8be215308f..2d49540fbd 100644
--- a/security/manager/ssl/nsNSSIOLayer.cpp
+++ b/security/manager/ssl/nsNSSIOLayer.cpp
@@ -2492,6 +2492,8 @@ loser:
return nullptr;
}
+// Please change getSignatureName in nsNSSCallbacks.cpp when changing the list
+// here.
static const SSLSignatureScheme sEnabledSignatureSchemes[] = {
ssl_sig_ecdsa_secp256r1_sha256,
ssl_sig_ecdsa_secp384r1_sha384,
@@ -2569,6 +2571,8 @@ nsSSLIOLayerSetOptions(PRFileDesc* fd, bool forSTARTTLS,
}
// Include a modest set of named groups.
+ // Please change getKeaGroupName in nsNSSCallbacks.cpp when changing the list
+ // here.
const SSLNamedGroup namedGroups[] = {
ssl_grp_ec_curve25519, ssl_grp_ec_secp256r1, ssl_grp_ec_secp384r1,
ssl_grp_ec_secp521r1, ssl_grp_ffdhe_2048, ssl_grp_ffdhe_3072
diff --git a/security/manager/ssl/nsSSLStatus.cpp b/security/manager/ssl/nsSSLStatus.cpp
index 1538b2aa7d..7f9915cb2a 100644
--- a/security/manager/ssl/nsSSLStatus.cpp
+++ b/security/manager/ssl/nsSSLStatus.cpp
@@ -77,6 +77,28 @@ nsSSLStatus::GetCipherName(nsACString& aCipherName)
}
NS_IMETHODIMP
+nsSSLStatus::GetKeaGroupName(nsACString& aKeaGroup)
+{
+ if (!mHaveCipherSuiteAndProtocol) {
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+
+ aKeaGroup.Assign(mKeaGroup);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsSSLStatus::GetSignatureSchemeName(nsACString& aSignatureScheme)
+{
+ if (!mHaveCipherSuiteAndProtocol) {
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+
+ aSignatureScheme.Assign(mSignatureSchemeName);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
nsSSLStatus::GetProtocolVersion(uint16_t* aProtocolVersion)
{
NS_ENSURE_ARG_POINTER(aProtocolVersion);
@@ -194,6 +216,15 @@ nsSSLStatus::Read(nsIObjectInputStream* aStream)
NS_ENSURE_SUCCESS(rv, rv);
}
+ // Added in version 2 (see bug 1304923).
+ if (streamFormatVersion >= 2) {
+ rv = aStream->ReadCString(mKeaGroup);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = aStream->ReadCString(mSignatureSchemeName);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
return NS_OK;
}
@@ -201,7 +232,7 @@ NS_IMETHODIMP
nsSSLStatus::Write(nsIObjectOutputStream* aStream)
{
// The current version of the binary stream format.
- const uint8_t STREAM_FORMAT_VERSION = 1;
+ const uint8_t STREAM_FORMAT_VERSION = 2;
nsresult rv = aStream->WriteCompoundObject(mServerCert,
NS_GET_IID(nsIX509Cert),
@@ -237,6 +268,13 @@ nsSSLStatus::Write(nsIObjectOutputStream* aStream)
rv = aStream->Write16(mCertificateTransparencyStatus);
NS_ENSURE_SUCCESS(rv, rv);
+ // Added in version 2.
+ rv = aStream->WriteStringZ(mKeaGroup.get());
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = aStream->WriteStringZ(mSignatureSchemeName.get());
+ NS_ENSURE_SUCCESS(rv, rv);
+
return NS_OK;
}
@@ -300,6 +338,8 @@ nsSSLStatus::nsSSLStatus()
, mProtocolVersion(0)
, mCertificateTransparencyStatus(nsISSLStatus::
CERTIFICATE_TRANSPARENCY_NOT_APPLICABLE)
+, mKeaGroup()
+, mSignatureSchemeName()
, mIsDomainMismatch(false)
, mIsNotValidAtThisTime(false)
, mIsUntrusted(false)
diff --git a/security/manager/ssl/nsSSLStatus.h b/security/manager/ssl/nsSSLStatus.h
index 2a8343407d..74f9d0f018 100644
--- a/security/manager/ssl/nsSSLStatus.h
+++ b/security/manager/ssl/nsSSLStatus.h
@@ -50,6 +50,8 @@ public:
uint16_t mCipherSuite;
uint16_t mProtocolVersion;
uint16_t mCertificateTransparencyStatus;
+ nsCString mKeaGroup;
+ nsCString mSignatureSchemeName;
bool mIsDomainMismatch;
bool mIsNotValidAtThisTime;
diff --git a/testing/web-platform/meta/navigation-timing/idlharness.html.ini b/testing/web-platform/meta/navigation-timing/idlharness.html.ini
index 4b43910f64..676f444a11 100644
--- a/testing/web-platform/meta/navigation-timing/idlharness.html.ini
+++ b/testing/web-platform/meta/navigation-timing/idlharness.html.ini
@@ -1,11 +1,5 @@
[idlharness.html]
type: testharness
- [PerformanceTiming interface: attribute secureConnectionStart]
- expected: FAIL
-
- [PerformanceTiming interface: window.performance.timing must inherit property "secureConnectionStart" with the proper type (10)]
- expected: FAIL
-
[Performance interface: existence and properties of interface object]
expected: FAIL
diff --git a/toolkit/components/telemetry/Histograms.json b/toolkit/components/telemetry/Histograms.json
index aa66fbe147..45ad662c72 100644
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -1502,12 +1502,24 @@
"n_buckets": 50,
"description": "HTTP page: DNS lookup time (ms)"
},
- "HTTP_PAGE_TCP_CONNECTION": {
+ "HTTP_PAGE_TLS_HANDSHAKE": {
+ "alert_emails": ["necko@mozilla.com", "pmcmanus@mozilla.com"],
+ "bug_numbers": [772589],
"expires_in_version": "never",
"kind": "exponential",
"high": 30000,
"n_buckets": 50,
- "description": "HTTP page: TCP connection setup (ms)"
+ "description": "HTTP page channel: After TCP SYN to Ready for HTTP (ms)"
+
+ },
+ "HTTP_PAGE_TCP_CONNECTION_2": {
+ "alert_emails": ["necko@mozilla.com", "pmcmanus@mozilla.com"],
+ "bug_numbers": [772589],
+ "expires_in_version": "never",
+ "kind": "exponential",
+ "high": 30000,
+ "n_buckets": 50,
+ "description": "HTTP page channel: TCP SYN to Ready for HTTP (ms)"
},
"HTTP_PAGE_OPEN_TO_FIRST_SENT": {
"expires_in_version": "never",
@@ -1621,12 +1633,23 @@
"n_buckets": 50,
"description": "HTTP subitem: DNS lookup time (ms)"
},
- "HTTP_SUB_TCP_CONNECTION": {
+ "HTTP_SUB_TLS_HANDSHAKE": {
+ "alert_emails": ["necko@mozilla.com", "pmcmanus@mozilla.com"],
+ "bug_numbers": [772589],
+ "expires_in_version": "never",
+ "kind": "exponential",
+ "high": 30000,
+ "n_buckets": 50,
+ "description": "HTTP subitem channel: After TCP SYN to Ready for HTTP (ms)"
+ },
+ "HTTP_SUB_TCP_CONNECTION_2": {
+ "alert_emails": ["necko@mozilla.com", "pmcmanus@mozilla.com"],
+ "bug_numbers": [772589],
"expires_in_version": "never",
"kind": "exponential",
"high": 30000,
"n_buckets": 50,
- "description": "HTTP subitem: TCP connection setup (ms)"
+ "description": "HTTP subitem channel: TCP SYN to Ready for HTTP (ms)"
},
"HTTP_SUB_OPEN_TO_FIRST_SENT": {
"expires_in_version": "never",
diff --git a/toolkit/components/telemetry/histogram-whitelists.json b/toolkit/components/telemetry/histogram-whitelists.json
index 52db331928..4861781998 100644
--- a/toolkit/components/telemetry/histogram-whitelists.json
+++ b/toolkit/components/telemetry/histogram-whitelists.json
@@ -333,7 +333,6 @@
"HTTP_PAGE_OPEN_TO_FIRST_RECEIVED",
"HTTP_PAGE_OPEN_TO_FIRST_SENT",
"HTTP_PAGE_REVALIDATION",
- "HTTP_PAGE_TCP_CONNECTION",
"HTTP_PROXY_TYPE",
"HTTP_REQUEST_PER_CONN",
"HTTP_REQUEST_PER_PAGE",
@@ -359,7 +358,6 @@
"HTTP_SUB_OPEN_TO_FIRST_RECEIVED",
"HTTP_SUB_OPEN_TO_FIRST_SENT",
"HTTP_SUB_REVALIDATION",
- "HTTP_SUB_TCP_CONNECTION",
"HTTP_TRANSACTION_IS_SSL",
"HTTP_TRANSACTION_USE_ALTSVC",
"HTTP_TRANSACTION_USE_ALTSVC_OE",
@@ -1167,7 +1165,6 @@
"HTTP_PAGE_OPEN_TO_FIRST_RECEIVED",
"HTTP_PAGE_OPEN_TO_FIRST_SENT",
"HTTP_PAGE_REVALIDATION",
- "HTTP_PAGE_TCP_CONNECTION",
"HTTP_PROXY_TYPE",
"HTTP_REQUEST_PER_CONN",
"HTTP_REQUEST_PER_PAGE",
@@ -1193,7 +1190,6 @@
"HTTP_SUB_OPEN_TO_FIRST_RECEIVED",
"HTTP_SUB_OPEN_TO_FIRST_SENT",
"HTTP_SUB_REVALIDATION",
- "HTTP_SUB_TCP_CONNECTION",
"HTTP_TRANSACTION_IS_SSL",
"HTTP_TRANSACTION_USE_ALTSVC",
"HTTP_TRANSACTION_USE_ALTSVC_OE",