Bug 1935611 - Fix libyuv/libpng link failed for loongarch64. r=glandium,tnikkel,ng
[gecko.git] / security / manager / ssl / IPCClientCertsParent.cpp
blob3b726df97959bfda9c64e57933c5a70112497915
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"
10 #include "nsNetCID.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));
28 if (!socketThread) {
29 return IPC_OK();
31 // Look for client certificates on the socket thread.
32 UniqueCERTCertList certList;
33 mozilla::SyncRunnable::DispatchToThread(
34 socketThread, NS_NewRunnableFunction(
35 "IPCClientCertsParent::RecvFindObjects", [&certList]() {
36 certList =
37 psm::FindClientCertificatesWithPrivateKeys();
38 }));
39 if (!certList) {
40 return IPC_OK();
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);
45 uint32_t slotType;
46 UniqueSECKEYPublicKey pubkey(CERT_ExtractPublicKey(n->cert));
47 if (!pubkey) {
48 return IPC_OK();
50 switch (SECKEY_GetPublicKeyType(pubkey.get())) {
51 case rsaKey:
52 case rsaPssKey: {
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));
60 break;
62 case ecKey: {
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));
68 break;
70 default:
71 n = CERT_LIST_NEXT(n);
72 continue;
74 Certificate cert(certDER, slotType);
75 aObjects->AppendElement(std::move(cert));
77 n = CERT_LIST_NEXT(n);
79 return IPC_OK();
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,
87 ByteArray aData,
88 ByteArray aParams,
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));
96 if (!cert) {
97 return IPC_OK();
99 UniqueSECKEYPrivateKey key(PK11_FindKeyByAnyCert(cert.get(), nullptr));
100 if (!key) {
101 return IPC_OK();
103 SECItem params = {siBuffer, aParams.data().Elements(),
104 static_cast<unsigned int>(aParams.data().Length())};
105 SECItem* paramsPtr = aParams.data().Length() > 0 ? &params : nullptr;
106 CK_MECHANISM_TYPE mechanism;
107 switch (key->keyType) {
108 case ecKey:
109 mechanism = CKM_ECDSA;
110 break;
111 case rsaKey:
112 mechanism = aParams.data().Length() > 0 ? CKM_RSA_PKCS_PSS : CKM_RSA_PKCS;
113 break;
114 default:
115 return IPC_OK();
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())};
121 SECStatus srv =
122 PK11_SignWithMechanism(key.get(), mechanism, paramsPtr, sig.get(), &hash);
123 if (srv != SECSuccess) {
124 return IPC_OK();
126 aSignature->data().AppendElements(sig->data, sig->len);
127 return IPC_OK();
130 } // namespace mozilla::psm