1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set sw=2 ts=8 et tw=80 : */
4 /* This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 #include "IPCClientCertsParent.h"
9 #include "ScopedNSSTypes.h"
11 #include "nsNSSComponent.h"
12 #include "nsNSSIOLayer.h"
14 #include "mozilla/SyncRunnable.h"
16 namespace mozilla::psm
{
18 IPCClientCertsParent::IPCClientCertsParent() = default;
20 // When the IPC client certs module needs to find certificate and key objects
21 // in the socket process, it will cause this function to be called in the
22 // parent process. The parent process needs to find all certificates with
23 // private keys (because these are potential client certificates).
24 mozilla::ipc::IPCResult
IPCClientCertsParent::RecvFindObjects(
25 nsTArray
<IPCClientCertObject
>* aObjects
) {
26 nsCOMPtr
<nsIEventTarget
> socketThread(
27 do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID
));
31 // Look for client certificates on the socket thread.
32 UniqueCERTCertList certList
;
33 mozilla::SyncRunnable::DispatchToThread(
34 socketThread
, NS_NewRunnableFunction(
35 "IPCClientCertsParent::RecvFindObjects", [&certList
]() {
37 psm::FindClientCertificatesWithPrivateKeys();
42 CERTCertListNode
* n
= CERT_LIST_HEAD(certList
);
43 while (!CERT_LIST_END(n
, certList
)) {
44 nsTArray
<uint8_t> certDER(n
->cert
->derCert
.data
, n
->cert
->derCert
.len
);
46 UniqueSECKEYPublicKey
pubkey(CERT_ExtractPublicKey(n
->cert
));
50 switch (SECKEY_GetPublicKeyType(pubkey
.get())) {
53 slotType
= PK11_DoesMechanism(n
->cert
->slot
, CKM_RSA_PKCS_PSS
)
54 ? kIPCClientCertsSlotTypeModern
55 : kIPCClientCertsSlotTypeLegacy
;
56 nsTArray
<uint8_t> modulus(pubkey
->u
.rsa
.modulus
.data
,
57 pubkey
->u
.rsa
.modulus
.len
);
58 RSAKey
rsakey(modulus
, certDER
, slotType
);
59 aObjects
->AppendElement(std::move(rsakey
));
63 slotType
= kIPCClientCertsSlotTypeModern
;
64 nsTArray
<uint8_t> params(pubkey
->u
.ec
.DEREncodedParams
.data
,
65 pubkey
->u
.ec
.DEREncodedParams
.len
);
66 ECKey
eckey(params
, certDER
, slotType
);
67 aObjects
->AppendElement(std::move(eckey
));
71 n
= CERT_LIST_NEXT(n
);
74 Certificate
cert(certDER
, slotType
);
75 aObjects
->AppendElement(std::move(cert
));
77 n
= CERT_LIST_NEXT(n
);
82 // When the IPC client certs module needs to sign data using a key managed by
83 // the parent process, it will cause this function to be called in the parent
84 // process. The parent process needs to find the key corresponding to the
85 // given certificate and sign the given data with the given parameters.
86 mozilla::ipc::IPCResult
IPCClientCertsParent::RecvSign(ByteArray aCert
,
89 ByteArray
* aSignature
) {
90 SECItem certItem
= {siBuffer
, const_cast<uint8_t*>(aCert
.data().Elements()),
91 static_cast<unsigned int>(aCert
.data().Length())};
92 aSignature
->data().Clear();
94 UniqueCERTCertificate
cert(CERT_NewTempCertificate(
95 CERT_GetDefaultCertDB(), &certItem
, nullptr, false, true));
99 UniqueSECKEYPrivateKey
key(PK11_FindKeyByAnyCert(cert
.get(), nullptr));
103 SECItem params
= {siBuffer
, aParams
.data().Elements(),
104 static_cast<unsigned int>(aParams
.data().Length())};
105 SECItem
* paramsPtr
= aParams
.data().Length() > 0 ? ¶ms
: nullptr;
106 CK_MECHANISM_TYPE mechanism
;
107 switch (key
->keyType
) {
109 mechanism
= CKM_ECDSA
;
112 mechanism
= aParams
.data().Length() > 0 ? CKM_RSA_PKCS_PSS
: CKM_RSA_PKCS
;
117 uint32_t len
= PK11_SignatureLen(key
.get());
118 UniqueSECItem
sig(::SECITEM_AllocItem(nullptr, nullptr, len
));
119 SECItem hash
= {siBuffer
, aData
.data().Elements(),
120 static_cast<unsigned int>(aData
.data().Length())};
122 PK11_SignWithMechanism(key
.get(), mechanism
, paramsPtr
, sig
.get(), &hash
);
123 if (srv
!= SECSuccess
) {
126 aSignature
->data().AppendElements(sig
->data
, sig
->len
);
130 } // namespace mozilla::psm