Skip to content

Commit 61bd4db

Browse files
committed
Bug 1535752 - avoid unnecessarily base64-encoding inputs to nsICertStorage when we already have DER r=mgoodwin
Differential Revision: https://phabricator.services.mozilla.com/D26034 --HG-- extra : moz-landing-system : lando
1 parent dd5a4c9 commit 61bd4db

File tree

7 files changed

+75
-89
lines changed

7 files changed

+75
-89
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

security/certverifier/NSSCertDBTrustDomain.cpp

Lines changed: 36 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -201,20 +201,20 @@ Result NSSCertDBTrustDomain::GetCertTrust(EndEntityOrCA endEntityOrCA,
201201
if (mCertDBTrustType == trustSSL) {
202202
int16_t revocationState;
203203

204-
nsAutoCString encIssuer;
205-
nsAutoCString encSerial;
206-
nsAutoCString encSubject;
207-
nsAutoCString encPubKey;
204+
nsTArray<uint8_t> issuerBytes;
205+
nsTArray<uint8_t> serialBytes;
206+
nsTArray<uint8_t> subjectBytes;
207+
nsTArray<uint8_t> pubKeyBytes;
208208

209-
nsresult nsrv = BuildRevocationCheckStrings(
210-
candidateCert.get(), encIssuer, encSerial, encSubject, encPubKey);
209+
nsresult nsrv = BuildRevocationCheckArrays(
210+
candidateCert, issuerBytes, serialBytes, subjectBytes, pubKeyBytes);
211211

212212
if (NS_FAILED(nsrv)) {
213213
return Result::FATAL_ERROR_LIBRARY_FAILURE;
214214
}
215215

216-
nsrv = mCertBlocklist->GetRevocationState(encIssuer, encSerial, encSubject,
217-
encPubKey, &revocationState);
216+
nsrv = mCertBlocklist->GetRevocationState(
217+
issuerBytes, serialBytes, subjectBytes, pubKeyBytes, &revocationState);
218218
if (NS_FAILED(nsrv)) {
219219
return Result::FATAL_ERROR_LIBRARY_FAILURE;
220220
}
@@ -1249,41 +1249,35 @@ nsresult DefaultServerNicknameForCert(const CERTCertificate* cert,
12491249
return NS_ERROR_FAILURE;
12501250
}
12511251

1252-
nsresult BuildRevocationCheckStrings(const CERTCertificate* cert,
1253-
/*out*/ nsCString& encIssuer,
1254-
/*out*/ nsCString& encSerial,
1255-
/*out*/ nsCString& encSubject,
1256-
/*out*/ nsCString& encPubKey) {
1257-
// Convert issuer, serial, subject and pubKey data to Base64 encoded DER
1258-
nsDependentCSubstring issuerString(
1259-
BitwiseCast<char*, uint8_t*>(cert->derIssuer.data), cert->derIssuer.len);
1260-
nsDependentCSubstring serialString(
1261-
BitwiseCast<char*, uint8_t*>(cert->serialNumber.data),
1262-
cert->serialNumber.len);
1263-
nsDependentCSubstring subjectString(
1264-
BitwiseCast<char*, uint8_t*>(cert->derSubject.data),
1265-
cert->derSubject.len);
1266-
nsDependentCSubstring pubKeyString(
1267-
BitwiseCast<char*, uint8_t*>(cert->derPublicKey.data),
1268-
cert->derPublicKey.len);
1269-
1270-
nsresult rv = Base64Encode(issuerString, encIssuer);
1271-
if (NS_FAILED(rv)) {
1272-
return rv;
1273-
}
1274-
rv = Base64Encode(serialString, encSerial);
1275-
if (NS_FAILED(rv)) {
1276-
return rv;
1277-
}
1278-
rv = Base64Encode(subjectString, encSubject);
1279-
if (NS_FAILED(rv)) {
1280-
return rv;
1281-
}
1282-
rv = Base64Encode(pubKeyString, encPubKey);
1283-
if (NS_FAILED(rv)) {
1284-
return rv;
1252+
nsresult BuildRevocationCheckArrays(const UniqueCERTCertificate& cert,
1253+
/*out*/ nsTArray<uint8_t>& issuerBytes,
1254+
/*out*/ nsTArray<uint8_t>& serialBytes,
1255+
/*out*/ nsTArray<uint8_t>& subjectBytes,
1256+
/*out*/ nsTArray<uint8_t>& pubKeyBytes) {
1257+
issuerBytes.Clear();
1258+
if (!issuerBytes.AppendElements(
1259+
BitwiseCast<char*, uint8_t*>(cert->derIssuer.data),
1260+
cert->derIssuer.len)) {
1261+
return NS_ERROR_OUT_OF_MEMORY;
1262+
}
1263+
serialBytes.Clear();
1264+
if (!serialBytes.AppendElements(
1265+
BitwiseCast<char*, uint8_t*>(cert->serialNumber.data),
1266+
cert->serialNumber.len)) {
1267+
return NS_ERROR_OUT_OF_MEMORY;
1268+
}
1269+
subjectBytes.Clear();
1270+
if (!subjectBytes.AppendElements(
1271+
BitwiseCast<char*, uint8_t*>(cert->derSubject.data),
1272+
cert->derSubject.len)) {
1273+
return NS_ERROR_OUT_OF_MEMORY;
1274+
}
1275+
pubKeyBytes.Clear();
1276+
if (!pubKeyBytes.AppendElements(
1277+
BitwiseCast<char*, uint8_t*>(cert->derPublicKey.data),
1278+
cert->derPublicKey.len)) {
1279+
return NS_ERROR_OUT_OF_MEMORY;
12851280
}
1286-
12871281
return NS_OK;
12881282
}
12891283

security/certverifier/NSSCertDBTrustDomain.h

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -60,28 +60,28 @@ nsresult DefaultServerNicknameForCert(const CERTCertificate* cert,
6060
/*out*/ nsCString& nickname);
6161

6262
/**
63-
* Build strings of base64 encoded issuer, serial, subject and public key data
64-
* from the supplied certificate for use in revocation checks.
63+
* Build nsTArray<uint8_t>s out of the issuer, serial, subject and public key
64+
* data from the supplied certificate for use in revocation checks.
6565
*
6666
* @param cert
6767
* The CERTCertificate* from which to extract the data.
6868
* @param out encIssuer
69-
* The string to populate with base64 encoded issuer data.
69+
* The array to populate with issuer data.
7070
* @param out encSerial
71-
* The string to populate with base64 encoded serial number data.
71+
* The array to populate with serial number data.
7272
* @param out encSubject
73-
* The string to populate with base64 encoded subject data.
73+
* The array to populate with subject data.
7474
* @param out encPubKey
75-
* The string to populate with base64 encoded public key data.
75+
* The array to populate with public key data.
7676
* @return
77-
* NS_OK, unless there's a Base64 encoding problem, in which case
78-
* NS_ERROR_FAILURE.
77+
* NS_OK, unless there's a memory allocation problem, in which case
78+
* NS_ERROR_OUT_OF_MEMORY.
7979
*/
80-
nsresult BuildRevocationCheckStrings(const CERTCertificate* cert,
81-
/*out*/ nsCString& encIssuer,
82-
/*out*/ nsCString& encSerial,
83-
/*out*/ nsCString& encSubject,
84-
/*out*/ nsCString& encPubKey);
80+
nsresult BuildRevocationCheckArrays(const UniqueCERTCertificate& cert,
81+
/*out*/ nsTArray<uint8_t>& issuerBytes,
82+
/*out*/ nsTArray<uint8_t>& serialBytes,
83+
/*out*/ nsTArray<uint8_t>& subjectBytes,
84+
/*out*/ nsTArray<uint8_t>& pubKeyBytes);
8585

8686
void SaveIntermediateCerts(const UniqueCERTCertList& certList);
8787

security/manager/ssl/CSTrustDomain.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,20 +44,20 @@ Result CSTrustDomain::GetCertTrust(EndEntityOrCA endEntityOrCA,
4444
return MapPRErrorCodeToResult(PR_GetError());
4545
}
4646

47-
nsAutoCString encIssuer;
48-
nsAutoCString encSerial;
49-
nsAutoCString encSubject;
50-
nsAutoCString encPubKey;
47+
nsTArray<uint8_t> issuerBytes;
48+
nsTArray<uint8_t> serialBytes;
49+
nsTArray<uint8_t> subjectBytes;
50+
nsTArray<uint8_t> pubKeyBytes;
5151

52-
nsresult nsrv = BuildRevocationCheckStrings(candidateCert.get(), encIssuer,
53-
encSerial, encSubject, encPubKey);
52+
nsresult nsrv = BuildRevocationCheckArrays(
53+
candidateCert, issuerBytes, serialBytes, subjectBytes, pubKeyBytes);
5454
if (NS_FAILED(nsrv)) {
5555
return Result::FATAL_ERROR_LIBRARY_FAILURE;
5656
}
5757

5858
int16_t revocationState;
59-
nsrv = mCertBlocklist->GetRevocationState(encIssuer, encSerial, encSubject,
60-
encPubKey, &revocationState);
59+
nsrv = mCertBlocklist->GetRevocationState(
60+
issuerBytes, serialBytes, subjectBytes, pubKeyBytes, &revocationState);
6161
if (NS_FAILED(nsrv)) {
6262
return Result::FATAL_ERROR_LIBRARY_FAILURE;
6363
}

security/manager/ssl/cert_storage/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,6 @@ nsstring = { path = "../../../../xpcom/rust/nsstring" }
1313
rkv = "^0.9"
1414
sha2 = "^0.7"
1515
style = { path = "../../../../servo/components/style" }
16+
thin-vec = { version = "0.1.0", features = ["gecko-ffi"] }
1617
time = "0.1"
1718
xpcom = { path = "../../../../xpcom/rust/xpcom" }

security/manager/ssl/cert_storage/src/lib.rs

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ extern crate nserror;
1010
extern crate nsstring;
1111
extern crate rkv;
1212
extern crate sha2;
13+
extern crate thin_vec;
1314
extern crate time;
1415
#[macro_use]
1516
extern crate xpcom;
@@ -36,6 +37,7 @@ use std::slice;
3637
use std::str;
3738
use std::sync::{Arc, Mutex, RwLock};
3839
use std::time::{Duration, SystemTime};
40+
use thin_vec::ThinVec;
3941
use xpcom::interfaces::{
4042
nsICertStorage, nsICertStorageCallback, nsIFile, nsIObserver, nsIPrefBranch, nsISupports,
4143
nsIThread,
@@ -799,24 +801,17 @@ impl CertStorage {
799801

800802
unsafe fn GetRevocationState(
801803
&self,
802-
issuer: *const nsACString,
803-
serial: *const nsACString,
804-
subject: *const nsACString,
805-
pub_key_base64: *const nsACString,
804+
issuer: *const ThinVec<u8>,
805+
serial: *const ThinVec<u8>,
806+
subject: *const ThinVec<u8>,
807+
pub_key: *const ThinVec<u8>,
806808
state: *mut i16,
807809
) -> nserror::nsresult {
808810
// TODO (bug 1541212): We really want to restrict this to non-main-threads only, but we
809811
// can't do so until bug 1406854 and bug 1534600 are fixed.
810-
if issuer.is_null() || serial.is_null() || subject.is_null() || pub_key_base64.is_null() {
812+
if issuer.is_null() || serial.is_null() || subject.is_null() || pub_key.is_null() {
811813
return NS_ERROR_FAILURE;
812814
}
813-
// TODO (bug 1535752): If we're calling this function when we already have binary data (e.g.
814-
// in a TrustDomain::GetCertTrust callback), we should be able to pass in the binary data
815-
// directly. See also bug 1535486.
816-
let issuer_decoded = try_ns!(base64::decode(&*issuer));
817-
let serial_decoded = try_ns!(base64::decode(&*serial));
818-
let subject_decoded = try_ns!(base64::decode(&*subject));
819-
let pub_key_decoded = try_ns!(base64::decode(&*pub_key_base64));
820815
*state = nsICertStorage::STATE_UNSET as i16;
821816
// The following is a way to ensure the DB has been opened while minimizing lock
822817
// acquisitions in the common (read-only) case. First we acquire a read lock and see if we
@@ -838,12 +833,7 @@ impl CertStorage {
838833
try_ns!(self.security_state.read())
839834
}
840835
};
841-
match ss.get_revocation_state(
842-
&issuer_decoded,
843-
&serial_decoded,
844-
&subject_decoded,
845-
&pub_key_decoded,
846-
) {
836+
match ss.get_revocation_state(&*issuer, &*serial, &*subject, &*pub_key) {
847837
Ok(st) => {
848838
*state = st;
849839
NS_OK

security/manager/ssl/nsICertStorage.idl

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -88,17 +88,17 @@ interface nsICertStorage : nsISupports {
8888
* Get the revocation state of a certificate. STATE_UNSET indicates the
8989
* certificate is not revoked. STATE_ENFORCE indicates the certificate is
9090
* revoked.
91-
* issuer - issuer name, DER, Base64 encoded
92-
* serial - serial number, DER, Base64 encoded
93-
* subject - subject name, DER, Base64 encoded
94-
* pubkey - public key, DER, Base64 encoded
91+
* issuer - issuer name, DER encoded
92+
* serial - serial number, DER encoded
93+
* subject - subject name, DER encoded
94+
* pubkey - public key, DER encoded
9595
* Must not be called from the main thread.
9696
*/
9797
[must_use]
98-
short getRevocationState(in ACString issuer,
99-
in ACString serial,
100-
in ACString subject,
101-
in ACString pubkey);
98+
short getRevocationState(in Array<octet> issuer,
99+
in Array<octet> serial,
100+
in Array<octet> subject,
101+
in Array<octet> pubkey);
102102

103103
/**
104104
* Get the CRLite enrollment status of a certificate.

0 commit comments

Comments
 (0)