nsNSSCertificate.cpp 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643
  1. /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "nsNSSCertificate.h"
  6. #include "CertVerifier.h"
  7. #include "ExtendedValidation.h"
  8. #include "NSSCertDBTrustDomain.h"
  9. #include "certdb.h"
  10. #include "mozilla/Base64.h"
  11. #include "mozilla/Casting.h"
  12. #include "mozilla/NotNull.h"
  13. #include "mozilla/Unused.h"
  14. #include "nsArray.h"
  15. #include "nsCOMPtr.h"
  16. #include "nsCRT.h"
  17. #include "nsICertificateDialogs.h"
  18. #include "nsIClassInfoImpl.h"
  19. #include "nsIObjectInputStream.h"
  20. #include "nsIObjectOutputStream.h"
  21. #include "nsISupportsPrimitives.h"
  22. #include "nsIURI.h"
  23. #include "nsIX509Cert.h"
  24. #include "nsNSSASN1Object.h"
  25. #include "nsNSSCertHelper.h"
  26. #include "nsNSSCertValidity.h"
  27. #include "nsNSSComponent.h" // for PIPNSS string bundle calls.
  28. #include "nsPK11TokenDB.h"
  29. #include "nsPKCS12Blob.h"
  30. #include "nsProxyRelease.h"
  31. #include "nsReadableUtils.h"
  32. #include "nsString.h"
  33. #include "nsThreadUtils.h"
  34. #include "nsUnicharUtils.h"
  35. #include "nsXULAppAPI.h"
  36. #include "nspr.h"
  37. #include "pkix/pkixnss.h"
  38. #include "pkix/pkixtypes.h"
  39. #include "pkix/Result.h"
  40. #include "prerror.h"
  41. #include "prmem.h"
  42. #include "prprf.h"
  43. #include "secasn1.h"
  44. #include "secder.h"
  45. #include "secerr.h"
  46. #include "ssl.h"
  47. #ifdef XP_WIN
  48. #include <winsock.h> // for htonl
  49. #endif
  50. using namespace mozilla;
  51. using namespace mozilla::psm;
  52. extern LazyLogModule gPIPNSSLog;
  53. // This is being stored in an uint32_t that can otherwise
  54. // only take values from nsIX509Cert's list of cert types.
  55. // As nsIX509Cert is frozen, we choose a value not contained
  56. // in the list to mean not yet initialized.
  57. #define CERT_TYPE_NOT_YET_INITIALIZED (1 << 30)
  58. NS_IMPL_ISUPPORTS(nsNSSCertificate,
  59. nsIX509Cert,
  60. nsISerializable,
  61. nsIClassInfo)
  62. static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
  63. /*static*/ nsNSSCertificate*
  64. nsNSSCertificate::Create(CERTCertificate* cert)
  65. {
  66. if (GeckoProcessType_Default != XRE_GetProcessType()) {
  67. NS_ERROR("Trying to initialize nsNSSCertificate in a non-chrome process!");
  68. return nullptr;
  69. }
  70. if (cert)
  71. return new nsNSSCertificate(cert);
  72. else
  73. return new nsNSSCertificate();
  74. }
  75. nsNSSCertificate*
  76. nsNSSCertificate::ConstructFromDER(char* certDER, int derLen)
  77. {
  78. // On non-chrome process prevent instantiation
  79. if (GeckoProcessType_Default != XRE_GetProcessType())
  80. return nullptr;
  81. nsNSSCertificate* newObject = nsNSSCertificate::Create();
  82. if (newObject && !newObject->InitFromDER(certDER, derLen)) {
  83. delete newObject;
  84. newObject = nullptr;
  85. }
  86. return newObject;
  87. }
  88. bool
  89. nsNSSCertificate::InitFromDER(char* certDER, int derLen)
  90. {
  91. nsNSSShutDownPreventionLock locker;
  92. if (isAlreadyShutDown())
  93. return false;
  94. if (!certDER || !derLen)
  95. return false;
  96. CERTCertificate* aCert = CERT_DecodeCertFromPackage(certDER, derLen);
  97. if (!aCert)
  98. return false;
  99. if (!aCert->dbhandle)
  100. {
  101. aCert->dbhandle = CERT_GetDefaultCertDB();
  102. }
  103. mCert.reset(aCert);
  104. return true;
  105. }
  106. nsNSSCertificate::nsNSSCertificate(CERTCertificate* cert)
  107. : mCert(nullptr)
  108. , mPermDelete(false)
  109. , mCertType(CERT_TYPE_NOT_YET_INITIALIZED)
  110. {
  111. #if defined(DEBUG)
  112. if (GeckoProcessType_Default != XRE_GetProcessType())
  113. NS_ERROR("Trying to initialize nsNSSCertificate in a non-chrome process!");
  114. #endif
  115. nsNSSShutDownPreventionLock locker;
  116. if (isAlreadyShutDown())
  117. return;
  118. if (cert) {
  119. mCert.reset(CERT_DupCertificate(cert));
  120. }
  121. }
  122. nsNSSCertificate::nsNSSCertificate()
  123. : mCert(nullptr)
  124. , mPermDelete(false)
  125. , mCertType(CERT_TYPE_NOT_YET_INITIALIZED)
  126. {
  127. if (GeckoProcessType_Default != XRE_GetProcessType())
  128. NS_ERROR("Trying to initialize nsNSSCertificate in a non-chrome process!");
  129. }
  130. nsNSSCertificate::~nsNSSCertificate()
  131. {
  132. nsNSSShutDownPreventionLock locker;
  133. if (isAlreadyShutDown()) {
  134. return;
  135. }
  136. destructorSafeDestroyNSSReference();
  137. shutdown(ShutdownCalledFrom::Object);
  138. }
  139. void nsNSSCertificate::virtualDestroyNSSReference()
  140. {
  141. destructorSafeDestroyNSSReference();
  142. }
  143. void nsNSSCertificate::destructorSafeDestroyNSSReference()
  144. {
  145. if (mPermDelete) {
  146. if (mCertType == nsNSSCertificate::USER_CERT) {
  147. nsCOMPtr<nsIInterfaceRequestor> cxt = new PipUIContext();
  148. PK11_DeleteTokenCertAndKey(mCert.get(), cxt);
  149. } else if (mCert->slot && !PK11_IsReadOnly(mCert->slot)) {
  150. // If the list of built-ins does contain a non-removable
  151. // copy of this certificate, our call will not remove
  152. // the certificate permanently, but rather remove all trust.
  153. SEC_DeletePermCertificate(mCert.get());
  154. }
  155. }
  156. mCert = nullptr;
  157. }
  158. nsresult
  159. nsNSSCertificate::GetCertType(uint32_t* aCertType)
  160. {
  161. if (mCertType == CERT_TYPE_NOT_YET_INITIALIZED) {
  162. // only determine cert type once and cache it
  163. mCertType = getCertType(mCert.get());
  164. }
  165. *aCertType = mCertType;
  166. return NS_OK;
  167. }
  168. NS_IMETHODIMP
  169. nsNSSCertificate::GetIsSelfSigned(bool* aIsSelfSigned)
  170. {
  171. NS_ENSURE_ARG(aIsSelfSigned);
  172. nsNSSShutDownPreventionLock locker;
  173. if (isAlreadyShutDown())
  174. return NS_ERROR_NOT_AVAILABLE;
  175. *aIsSelfSigned = mCert->isRoot;
  176. return NS_OK;
  177. }
  178. NS_IMETHODIMP
  179. nsNSSCertificate::GetIsBuiltInRoot(bool* aIsBuiltInRoot)
  180. {
  181. NS_ENSURE_ARG(aIsBuiltInRoot);
  182. nsNSSShutDownPreventionLock locker;
  183. if (isAlreadyShutDown()) {
  184. return NS_ERROR_NOT_AVAILABLE;
  185. }
  186. pkix::Result rv = IsCertBuiltInRoot(mCert.get(), *aIsBuiltInRoot);
  187. if (rv != pkix::Result::Success) {
  188. return NS_ERROR_FAILURE;
  189. }
  190. return NS_OK;
  191. }
  192. nsresult
  193. nsNSSCertificate::MarkForPermDeletion()
  194. {
  195. nsNSSShutDownPreventionLock locker;
  196. if (isAlreadyShutDown())
  197. return NS_ERROR_NOT_AVAILABLE;
  198. // make sure user is logged in to the token
  199. nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext();
  200. if (mCert->slot && PK11_NeedLogin(mCert->slot) &&
  201. !PK11_NeedUserInit(mCert->slot) && !PK11_IsInternal(mCert->slot)) {
  202. if (SECSuccess != PK11_Authenticate(mCert->slot, true, ctx)) {
  203. return NS_ERROR_FAILURE;
  204. }
  205. }
  206. mPermDelete = true;
  207. return NS_OK;
  208. }
  209. /**
  210. * Appends a pipnss bundle string to the given string.
  211. *
  212. * @param nssComponent For accessing the string bundle.
  213. * @param bundleKey Key for the string to append.
  214. * @param currentText The text to append to, using commas as separators.
  215. */
  216. template<size_t N>
  217. void
  218. AppendBundleString(const NotNull<nsCOMPtr<nsINSSComponent>>& nssComponent,
  219. const char (&bundleKey)[N],
  220. /*in/out*/ nsAString& currentText)
  221. {
  222. nsAutoString bundleString;
  223. nsresult rv = nssComponent->GetPIPNSSBundleString(bundleKey, bundleString);
  224. if (NS_FAILED(rv)) {
  225. return;
  226. }
  227. if (!currentText.IsEmpty()) {
  228. currentText.Append(',');
  229. }
  230. currentText.Append(bundleString);
  231. }
  232. NS_IMETHODIMP
  233. nsNSSCertificate::GetKeyUsages(nsAString& text)
  234. {
  235. text.Truncate();
  236. nsCOMPtr<nsINSSComponent> nssComponent = do_GetService(kNSSComponentCID);
  237. if (!nssComponent) {
  238. return NS_ERROR_FAILURE;
  239. }
  240. if (!mCert) {
  241. return NS_ERROR_FAILURE;
  242. }
  243. if (!mCert->extensions) {
  244. return NS_OK;
  245. }
  246. ScopedAutoSECItem keyUsageItem;
  247. if (CERT_FindKeyUsageExtension(mCert.get(), &keyUsageItem) != SECSuccess) {
  248. return PORT_GetError() == SEC_ERROR_EXTENSION_NOT_FOUND ? NS_OK
  249. : NS_ERROR_FAILURE;
  250. }
  251. unsigned char keyUsage = 0;
  252. if (keyUsageItem.len) {
  253. keyUsage = keyUsageItem.data[0];
  254. }
  255. NotNull<nsCOMPtr<nsINSSComponent>> wrappedNSSComponent =
  256. WrapNotNull(nssComponent);
  257. if (keyUsage & KU_DIGITAL_SIGNATURE) {
  258. AppendBundleString(wrappedNSSComponent, "CertDumpKUSign", text);
  259. }
  260. if (keyUsage & KU_NON_REPUDIATION) {
  261. AppendBundleString(wrappedNSSComponent, "CertDumpKUNonRep", text);
  262. }
  263. if (keyUsage & KU_KEY_ENCIPHERMENT) {
  264. AppendBundleString(wrappedNSSComponent, "CertDumpKUEnc", text);
  265. }
  266. if (keyUsage & KU_DATA_ENCIPHERMENT) {
  267. AppendBundleString(wrappedNSSComponent, "CertDumpKUDEnc", text);
  268. }
  269. if (keyUsage & KU_KEY_AGREEMENT) {
  270. AppendBundleString(wrappedNSSComponent, "CertDumpKUKA", text);
  271. }
  272. if (keyUsage & KU_KEY_CERT_SIGN) {
  273. AppendBundleString(wrappedNSSComponent, "CertDumpKUCertSign", text);
  274. }
  275. if (keyUsage & KU_CRL_SIGN) {
  276. AppendBundleString(wrappedNSSComponent, "CertDumpKUCRLSign", text);
  277. }
  278. return NS_OK;
  279. }
  280. NS_IMETHODIMP
  281. nsNSSCertificate::GetDbKey(nsACString& aDbKey)
  282. {
  283. nsNSSShutDownPreventionLock locker;
  284. if (isAlreadyShutDown()) {
  285. return NS_ERROR_NOT_AVAILABLE;
  286. }
  287. return GetDbKey(mCert, aDbKey);
  288. }
  289. nsresult
  290. nsNSSCertificate::GetDbKey(const UniqueCERTCertificate& cert, nsACString& aDbKey)
  291. {
  292. static_assert(sizeof(uint64_t) == 8, "type size sanity check");
  293. static_assert(sizeof(uint32_t) == 4, "type size sanity check");
  294. // The format of the key is the base64 encoding of the following:
  295. // 4 bytes: {0, 0, 0, 0} (this was intended to be the module ID, but it was
  296. // never implemented)
  297. // 4 bytes: {0, 0, 0, 0} (this was intended to be the slot ID, but it was
  298. // never implemented)
  299. // 4 bytes: <serial number length in big-endian order>
  300. // 4 bytes: <DER-encoded issuer distinguished name length in big-endian order>
  301. // n bytes: <bytes of serial number>
  302. // m bytes: <DER-encoded issuer distinguished name>
  303. nsAutoCString buf;
  304. const char leadingZeroes[] = {0, 0, 0, 0, 0, 0, 0, 0};
  305. buf.Append(leadingZeroes, sizeof(leadingZeroes));
  306. uint32_t serialNumberLen = htonl(cert->serialNumber.len);
  307. buf.Append(BitwiseCast<const char*, const uint32_t*>(&serialNumberLen),
  308. sizeof(uint32_t));
  309. uint32_t issuerLen = htonl(cert->derIssuer.len);
  310. buf.Append(BitwiseCast<const char*, const uint32_t*>(&issuerLen),
  311. sizeof(uint32_t));
  312. buf.Append(BitwiseCast<char*, unsigned char*>(cert->serialNumber.data),
  313. cert->serialNumber.len);
  314. buf.Append(BitwiseCast<char*, unsigned char*>(cert->derIssuer.data),
  315. cert->derIssuer.len);
  316. return Base64Encode(buf, aDbKey);
  317. }
  318. NS_IMETHODIMP
  319. nsNSSCertificate::GetWindowTitle(nsAString& aWindowTitle)
  320. {
  321. nsNSSShutDownPreventionLock locker;
  322. if (isAlreadyShutDown()) {
  323. return NS_ERROR_NOT_AVAILABLE;
  324. }
  325. aWindowTitle.Truncate();
  326. if (!mCert) {
  327. NS_ERROR("Somehow got nullptr for mCert in nsNSSCertificate.");
  328. return NS_ERROR_FAILURE;
  329. }
  330. UniquePORTString commonName(CERT_GetCommonName(&mCert->subject));
  331. const char* titleOptions[] = {
  332. mCert->nickname,
  333. commonName.get(),
  334. mCert->subjectName,
  335. mCert->emailAddr
  336. };
  337. nsAutoCString titleOption;
  338. for (size_t i = 0; i < ArrayLength(titleOptions); i++) {
  339. titleOption = titleOptions[i];
  340. if (titleOption.Length() > 0 && IsUTF8(titleOption)) {
  341. CopyUTF8toUTF16(titleOption, aWindowTitle);
  342. return NS_OK;
  343. }
  344. }
  345. return NS_OK;
  346. }
  347. NS_IMETHODIMP
  348. nsNSSCertificate::GetNickname(nsAString& aNickname)
  349. {
  350. nsNSSShutDownPreventionLock locker;
  351. if (isAlreadyShutDown())
  352. return NS_ERROR_NOT_AVAILABLE;
  353. if (mCert->nickname) {
  354. CopyUTF8toUTF16(mCert->nickname, aNickname);
  355. } else {
  356. nsresult rv;
  357. nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
  358. if (NS_FAILED(rv) || !nssComponent) {
  359. return NS_ERROR_FAILURE;
  360. }
  361. nssComponent->GetPIPNSSBundleString("CertNoNickname", aNickname);
  362. }
  363. return NS_OK;
  364. }
  365. NS_IMETHODIMP
  366. nsNSSCertificate::GetEmailAddress(nsAString& aEmailAddress)
  367. {
  368. nsNSSShutDownPreventionLock locker;
  369. if (isAlreadyShutDown())
  370. return NS_ERROR_NOT_AVAILABLE;
  371. if (mCert->emailAddr) {
  372. CopyUTF8toUTF16(mCert->emailAddr, aEmailAddress);
  373. } else {
  374. nsresult rv;
  375. nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
  376. if (NS_FAILED(rv) || !nssComponent) {
  377. return NS_ERROR_FAILURE;
  378. }
  379. nssComponent->GetPIPNSSBundleString("CertNoEmailAddress", aEmailAddress);
  380. }
  381. return NS_OK;
  382. }
  383. NS_IMETHODIMP
  384. nsNSSCertificate::GetEmailAddresses(uint32_t* aLength, char16_t*** aAddresses)
  385. {
  386. nsNSSShutDownPreventionLock locker;
  387. if (isAlreadyShutDown())
  388. return NS_ERROR_NOT_AVAILABLE;
  389. NS_ENSURE_ARG(aLength);
  390. NS_ENSURE_ARG(aAddresses);
  391. *aLength = 0;
  392. const char* aAddr;
  393. for (aAddr = CERT_GetFirstEmailAddress(mCert.get())
  394. ;
  395. aAddr
  396. ;
  397. aAddr = CERT_GetNextEmailAddress(mCert.get(), aAddr))
  398. {
  399. ++(*aLength);
  400. }
  401. *aAddresses = (char16_t**) moz_xmalloc(sizeof(char16_t*) * (*aLength));
  402. if (!*aAddresses)
  403. return NS_ERROR_OUT_OF_MEMORY;
  404. uint32_t iAddr;
  405. for (aAddr = CERT_GetFirstEmailAddress(mCert.get()), iAddr = 0
  406. ;
  407. aAddr
  408. ;
  409. aAddr = CERT_GetNextEmailAddress(mCert.get(), aAddr), ++iAddr)
  410. {
  411. (*aAddresses)[iAddr] = ToNewUnicode(NS_ConvertUTF8toUTF16(aAddr));
  412. }
  413. return NS_OK;
  414. }
  415. NS_IMETHODIMP
  416. nsNSSCertificate::ContainsEmailAddress(const nsAString& aEmailAddress,
  417. bool* result)
  418. {
  419. nsNSSShutDownPreventionLock locker;
  420. if (isAlreadyShutDown())
  421. return NS_ERROR_NOT_AVAILABLE;
  422. NS_ENSURE_ARG(result);
  423. *result = false;
  424. const char* aAddr = nullptr;
  425. for (aAddr = CERT_GetFirstEmailAddress(mCert.get())
  426. ;
  427. aAddr
  428. ;
  429. aAddr = CERT_GetNextEmailAddress(mCert.get(), aAddr))
  430. {
  431. NS_ConvertUTF8toUTF16 certAddr(aAddr);
  432. ToLowerCase(certAddr);
  433. nsAutoString testAddr(aEmailAddress);
  434. ToLowerCase(testAddr);
  435. if (certAddr == testAddr)
  436. {
  437. *result = true;
  438. break;
  439. }
  440. }
  441. return NS_OK;
  442. }
  443. NS_IMETHODIMP
  444. nsNSSCertificate::GetCommonName(nsAString& aCommonName)
  445. {
  446. nsNSSShutDownPreventionLock locker;
  447. if (isAlreadyShutDown())
  448. return NS_ERROR_NOT_AVAILABLE;
  449. aCommonName.Truncate();
  450. if (mCert) {
  451. UniquePORTString commonName(CERT_GetCommonName(&mCert->subject));
  452. if (commonName) {
  453. aCommonName = NS_ConvertUTF8toUTF16(commonName.get());
  454. }
  455. }
  456. return NS_OK;
  457. }
  458. NS_IMETHODIMP
  459. nsNSSCertificate::GetOrganization(nsAString& aOrganization)
  460. {
  461. nsNSSShutDownPreventionLock locker;
  462. if (isAlreadyShutDown())
  463. return NS_ERROR_NOT_AVAILABLE;
  464. aOrganization.Truncate();
  465. if (mCert) {
  466. UniquePORTString organization(CERT_GetOrgName(&mCert->subject));
  467. if (organization) {
  468. aOrganization = NS_ConvertUTF8toUTF16(organization.get());
  469. }
  470. }
  471. return NS_OK;
  472. }
  473. NS_IMETHODIMP
  474. nsNSSCertificate::GetIssuerCommonName(nsAString& aCommonName)
  475. {
  476. nsNSSShutDownPreventionLock locker;
  477. if (isAlreadyShutDown())
  478. return NS_ERROR_NOT_AVAILABLE;
  479. aCommonName.Truncate();
  480. if (mCert) {
  481. UniquePORTString commonName(CERT_GetCommonName(&mCert->issuer));
  482. if (commonName) {
  483. aCommonName = NS_ConvertUTF8toUTF16(commonName.get());
  484. }
  485. }
  486. return NS_OK;
  487. }
  488. NS_IMETHODIMP
  489. nsNSSCertificate::GetIssuerOrganization(nsAString& aOrganization)
  490. {
  491. nsNSSShutDownPreventionLock locker;
  492. if (isAlreadyShutDown())
  493. return NS_ERROR_NOT_AVAILABLE;
  494. aOrganization.Truncate();
  495. if (mCert) {
  496. UniquePORTString organization(CERT_GetOrgName(&mCert->issuer));
  497. if (organization) {
  498. aOrganization = NS_ConvertUTF8toUTF16(organization.get());
  499. }
  500. }
  501. return NS_OK;
  502. }
  503. NS_IMETHODIMP
  504. nsNSSCertificate::GetIssuerOrganizationUnit(nsAString& aOrganizationUnit)
  505. {
  506. nsNSSShutDownPreventionLock locker;
  507. if (isAlreadyShutDown())
  508. return NS_ERROR_NOT_AVAILABLE;
  509. aOrganizationUnit.Truncate();
  510. if (mCert) {
  511. UniquePORTString organizationUnit(CERT_GetOrgUnitName(&mCert->issuer));
  512. if (organizationUnit) {
  513. aOrganizationUnit = NS_ConvertUTF8toUTF16(organizationUnit.get());
  514. }
  515. }
  516. return NS_OK;
  517. }
  518. NS_IMETHODIMP
  519. nsNSSCertificate::GetIssuer(nsIX509Cert** aIssuer)
  520. {
  521. nsNSSShutDownPreventionLock locker;
  522. if (isAlreadyShutDown())
  523. return NS_ERROR_NOT_AVAILABLE;
  524. NS_ENSURE_ARG(aIssuer);
  525. *aIssuer = nullptr;
  526. nsCOMPtr<nsIArray> chain;
  527. nsresult rv;
  528. rv = GetChain(getter_AddRefs(chain));
  529. NS_ENSURE_SUCCESS(rv, rv);
  530. uint32_t length;
  531. if (!chain || NS_FAILED(chain->GetLength(&length)) || length == 0) {
  532. return NS_ERROR_UNEXPECTED;
  533. }
  534. if (length == 1) { // No known issuer
  535. return NS_OK;
  536. }
  537. nsCOMPtr<nsIX509Cert> cert;
  538. chain->QueryElementAt(1, NS_GET_IID(nsIX509Cert), getter_AddRefs(cert));
  539. if (!cert) {
  540. return NS_ERROR_UNEXPECTED;
  541. }
  542. cert.forget(aIssuer);
  543. return NS_OK;
  544. }
  545. NS_IMETHODIMP
  546. nsNSSCertificate::GetOrganizationalUnit(nsAString& aOrganizationalUnit)
  547. {
  548. nsNSSShutDownPreventionLock locker;
  549. if (isAlreadyShutDown())
  550. return NS_ERROR_NOT_AVAILABLE;
  551. aOrganizationalUnit.Truncate();
  552. if (mCert) {
  553. UniquePORTString orgunit(CERT_GetOrgUnitName(&mCert->subject));
  554. if (orgunit) {
  555. aOrganizationalUnit = NS_ConvertUTF8toUTF16(orgunit.get());
  556. }
  557. }
  558. return NS_OK;
  559. }
  560. NS_IMETHODIMP
  561. nsNSSCertificate::GetChain(nsIArray** _rvChain)
  562. {
  563. nsNSSShutDownPreventionLock locker;
  564. if (isAlreadyShutDown())
  565. return NS_ERROR_NOT_AVAILABLE;
  566. NS_ENSURE_ARG(_rvChain);
  567. MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("Getting chain for \"%s\"\n", mCert->nickname));
  568. mozilla::pkix::Time now(mozilla::pkix::Now());
  569. RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
  570. NS_ENSURE_TRUE(certVerifier, NS_ERROR_UNEXPECTED);
  571. UniqueCERTCertList nssChain;
  572. // We want to test all usages, but we start with server because most of the
  573. // time Firefox users care about server certs.
  574. if (certVerifier->VerifyCert(mCert.get(), certificateUsageSSLServer, now,
  575. nullptr, /*XXX fixme*/
  576. nullptr, /* hostname */
  577. nssChain,
  578. CertVerifier::FLAG_LOCAL_ONLY)
  579. != mozilla::pkix::Success) {
  580. nssChain = nullptr;
  581. // keep going
  582. }
  583. // This is the whitelist of all non-SSLServer usages that are supported by
  584. // verifycert.
  585. const int otherUsagesToTest = certificateUsageSSLClient |
  586. certificateUsageSSLCA |
  587. certificateUsageEmailSigner |
  588. certificateUsageEmailRecipient |
  589. certificateUsageObjectSigner |
  590. certificateUsageStatusResponder;
  591. for (int usage = certificateUsageSSLClient;
  592. usage < certificateUsageAnyCA && !nssChain;
  593. usage = usage << 1) {
  594. if ((usage & otherUsagesToTest) == 0) {
  595. continue;
  596. }
  597. MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
  598. ("pipnss: PKIX attempting chain(%d) for '%s'\n",
  599. usage, mCert->nickname));
  600. if (certVerifier->VerifyCert(mCert.get(), usage, now,
  601. nullptr, /*XXX fixme*/
  602. nullptr, /*hostname*/
  603. nssChain,
  604. CertVerifier::FLAG_LOCAL_ONLY)
  605. != mozilla::pkix::Success) {
  606. nssChain = nullptr;
  607. // keep going
  608. }
  609. }
  610. if (!nssChain) {
  611. // There is not verified path for the chain, however we still want to
  612. // present to the user as much of a possible chain as possible, in the case
  613. // where there was a problem with the cert or the issuers.
  614. MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
  615. ("pipnss: getchain :CertVerify failed to get chain for '%s'\n",
  616. mCert->nickname));
  617. nssChain = UniqueCERTCertList(
  618. CERT_GetCertChainFromCert(mCert.get(), PR_Now(), certUsageSSLClient));
  619. }
  620. if (!nssChain) {
  621. return NS_ERROR_FAILURE;
  622. }
  623. // enumerate the chain for scripting purposes
  624. nsCOMPtr<nsIMutableArray> array = nsArrayBase::Create();
  625. if (!array) {
  626. return NS_ERROR_FAILURE;
  627. }
  628. CERTCertListNode* node;
  629. for (node = CERT_LIST_HEAD(nssChain.get());
  630. !CERT_LIST_END(node, nssChain.get());
  631. node = CERT_LIST_NEXT(node)) {
  632. MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
  633. ("adding %s to chain\n", node->cert->nickname));
  634. nsCOMPtr<nsIX509Cert> cert = nsNSSCertificate::Create(node->cert);
  635. array->AppendElement(cert, false);
  636. }
  637. *_rvChain = array;
  638. NS_IF_ADDREF(*_rvChain);
  639. return NS_OK;
  640. }
  641. NS_IMETHODIMP
  642. nsNSSCertificate::GetAllTokenNames(uint32_t* aLength, char16_t*** aTokenNames)
  643. {
  644. nsNSSShutDownPreventionLock locker;
  645. if (isAlreadyShutDown())
  646. return NS_ERROR_NOT_AVAILABLE;
  647. NS_ENSURE_ARG(aLength);
  648. NS_ENSURE_ARG(aTokenNames);
  649. *aLength = 0;
  650. *aTokenNames = nullptr;
  651. // Get the slots from NSS
  652. MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("Getting slots for \"%s\"\n", mCert->nickname));
  653. UniquePK11SlotList slots(PK11_GetAllSlotsForCert(mCert.get(), nullptr));
  654. if (!slots) {
  655. if (PORT_GetError() == SEC_ERROR_NO_TOKEN) {
  656. return NS_OK; // List of slots is empty, return empty array
  657. }
  658. return NS_ERROR_FAILURE;
  659. }
  660. // read the token names from slots
  661. PK11SlotListElement* le;
  662. for (le = slots->head; le; le = le->next) {
  663. ++(*aLength);
  664. }
  665. *aTokenNames = (char16_t**) moz_xmalloc(sizeof(char16_t*) * (*aLength));
  666. if (!*aTokenNames) {
  667. *aLength = 0;
  668. return NS_ERROR_OUT_OF_MEMORY;
  669. }
  670. uint32_t iToken;
  671. for (le = slots->head, iToken = 0; le; le = le->next, ++iToken) {
  672. char* token = PK11_GetTokenName(le->slot);
  673. (*aTokenNames)[iToken] = ToNewUnicode(NS_ConvertUTF8toUTF16(token));
  674. if (!(*aTokenNames)[iToken]) {
  675. NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(iToken, *aTokenNames);
  676. *aLength = 0;
  677. *aTokenNames = nullptr;
  678. return NS_ERROR_OUT_OF_MEMORY;
  679. }
  680. }
  681. return NS_OK;
  682. }
  683. NS_IMETHODIMP
  684. nsNSSCertificate::GetSubjectName(nsAString& _subjectName)
  685. {
  686. nsNSSShutDownPreventionLock locker;
  687. if (isAlreadyShutDown())
  688. return NS_ERROR_NOT_AVAILABLE;
  689. _subjectName.Truncate();
  690. if (mCert->subjectName) {
  691. _subjectName = NS_ConvertUTF8toUTF16(mCert->subjectName);
  692. }
  693. return NS_OK;
  694. }
  695. NS_IMETHODIMP
  696. nsNSSCertificate::GetIssuerName(nsAString& _issuerName)
  697. {
  698. nsNSSShutDownPreventionLock locker;
  699. if (isAlreadyShutDown())
  700. return NS_ERROR_NOT_AVAILABLE;
  701. _issuerName.Truncate();
  702. if (mCert->issuerName) {
  703. _issuerName = NS_ConvertUTF8toUTF16(mCert->issuerName);
  704. }
  705. return NS_OK;
  706. }
  707. NS_IMETHODIMP
  708. nsNSSCertificate::GetSerialNumber(nsAString& _serialNumber)
  709. {
  710. nsNSSShutDownPreventionLock locker;
  711. if (isAlreadyShutDown())
  712. return NS_ERROR_NOT_AVAILABLE;
  713. _serialNumber.Truncate();
  714. UniquePORTString tmpstr(CERT_Hexify(&mCert->serialNumber, 1));
  715. if (tmpstr) {
  716. _serialNumber = NS_ConvertASCIItoUTF16(tmpstr.get());
  717. return NS_OK;
  718. }
  719. return NS_ERROR_FAILURE;
  720. }
  721. nsresult
  722. nsNSSCertificate::GetCertificateHash(nsAString& aFingerprint, SECOidTag aHashAlg)
  723. {
  724. nsNSSShutDownPreventionLock locker;
  725. if (isAlreadyShutDown()) {
  726. return NS_ERROR_NOT_AVAILABLE;
  727. }
  728. aFingerprint.Truncate();
  729. Digest digest;
  730. nsresult rv = digest.DigestBuf(aHashAlg, mCert->derCert.data,
  731. mCert->derCert.len);
  732. if (NS_FAILED(rv)) {
  733. return rv;
  734. }
  735. // CERT_Hexify's second argument is an int that is interpreted as a boolean
  736. UniquePORTString fpStr(CERT_Hexify(const_cast<SECItem*>(&digest.get()), 1));
  737. if (!fpStr) {
  738. return NS_ERROR_FAILURE;
  739. }
  740. aFingerprint.AssignASCII(fpStr.get());
  741. return NS_OK;
  742. }
  743. NS_IMETHODIMP
  744. nsNSSCertificate::GetSha256Fingerprint(nsAString& aSha256Fingerprint)
  745. {
  746. return GetCertificateHash(aSha256Fingerprint, SEC_OID_SHA256);
  747. }
  748. NS_IMETHODIMP
  749. nsNSSCertificate::GetSha1Fingerprint(nsAString& _sha1Fingerprint)
  750. {
  751. return GetCertificateHash(_sha1Fingerprint, SEC_OID_SHA1);
  752. }
  753. NS_IMETHODIMP
  754. nsNSSCertificate::GetTokenName(nsAString& aTokenName)
  755. {
  756. nsNSSShutDownPreventionLock locker;
  757. if (isAlreadyShutDown())
  758. return NS_ERROR_NOT_AVAILABLE;
  759. aTokenName.Truncate();
  760. if (mCert) {
  761. // HACK alert
  762. // When the trust of a builtin cert is modified, NSS copies it into the
  763. // cert db. At this point, it is now "managed" by the user, and should
  764. // not be listed with the builtins. However, in the collection code
  765. // used by PK11_ListCerts, the cert is found in the temp db, where it
  766. // has been loaded from the token. Though the trust is correct (grabbed
  767. // from the cert db), the source is wrong. I believe this is a safe
  768. // way to work around this.
  769. if (mCert->slot) {
  770. char* token = PK11_GetTokenName(mCert->slot);
  771. if (token) {
  772. aTokenName = NS_ConvertUTF8toUTF16(token);
  773. }
  774. } else {
  775. nsresult rv;
  776. nsAutoString tok;
  777. nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
  778. if (NS_FAILED(rv)) return rv;
  779. rv = nssComponent->GetPIPNSSBundleString("InternalToken", tok);
  780. if (NS_SUCCEEDED(rv))
  781. aTokenName = tok;
  782. }
  783. }
  784. return NS_OK;
  785. }
  786. NS_IMETHODIMP
  787. nsNSSCertificate::GetSha256SubjectPublicKeyInfoDigest(nsACString& aSha256SPKIDigest)
  788. {
  789. nsNSSShutDownPreventionLock locker;
  790. if (isAlreadyShutDown()) {
  791. return NS_ERROR_NOT_AVAILABLE;
  792. }
  793. aSha256SPKIDigest.Truncate();
  794. Digest digest;
  795. nsresult rv = digest.DigestBuf(SEC_OID_SHA256, mCert->derPublicKey.data,
  796. mCert->derPublicKey.len);
  797. if (NS_WARN_IF(NS_FAILED(rv))) {
  798. return rv;
  799. }
  800. rv = Base64Encode(nsDependentCSubstring(
  801. BitwiseCast<char*, unsigned char*>(digest.get().data),
  802. digest.get().len),
  803. aSha256SPKIDigest);
  804. if (NS_WARN_IF(NS_FAILED(rv))) {
  805. return rv;
  806. }
  807. return NS_OK;
  808. }
  809. NS_IMETHODIMP
  810. nsNSSCertificate::GetRawDER(uint32_t* aLength, uint8_t** aArray)
  811. {
  812. nsNSSShutDownPreventionLock locker;
  813. if (isAlreadyShutDown())
  814. return NS_ERROR_NOT_AVAILABLE;
  815. if (mCert) {
  816. *aArray = (uint8_t*)moz_xmalloc(mCert->derCert.len);
  817. if (*aArray) {
  818. memcpy(*aArray, mCert->derCert.data, mCert->derCert.len);
  819. *aLength = mCert->derCert.len;
  820. return NS_OK;
  821. }
  822. }
  823. *aLength = 0;
  824. return NS_ERROR_FAILURE;
  825. }
  826. NS_IMETHODIMP
  827. nsNSSCertificate::ExportAsCMS(uint32_t chainMode,
  828. uint32_t* aLength, uint8_t** aArray)
  829. {
  830. NS_ENSURE_ARG(aLength);
  831. NS_ENSURE_ARG(aArray);
  832. nsNSSShutDownPreventionLock locker;
  833. if (isAlreadyShutDown())
  834. return NS_ERROR_NOT_AVAILABLE;
  835. if (!mCert)
  836. return NS_ERROR_FAILURE;
  837. switch (chainMode) {
  838. case nsIX509Cert::CMS_CHAIN_MODE_CertOnly:
  839. case nsIX509Cert::CMS_CHAIN_MODE_CertChain:
  840. case nsIX509Cert::CMS_CHAIN_MODE_CertChainWithRoot:
  841. break;
  842. default:
  843. return NS_ERROR_INVALID_ARG;
  844. }
  845. UniqueNSSCMSMessage cmsg(NSS_CMSMessage_Create(nullptr));
  846. if (!cmsg) {
  847. MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
  848. ("nsNSSCertificate::ExportAsCMS - can't create CMS message\n"));
  849. return NS_ERROR_OUT_OF_MEMORY;
  850. }
  851. // first, create SignedData with the certificate only (no chain)
  852. UniqueNSSCMSSignedData sigd(
  853. NSS_CMSSignedData_CreateCertsOnly(cmsg.get(), mCert.get(), false));
  854. if (!sigd) {
  855. MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
  856. ("nsNSSCertificate::ExportAsCMS - can't create SignedData\n"));
  857. return NS_ERROR_FAILURE;
  858. }
  859. // Calling NSS_CMSSignedData_CreateCertsOnly() will not allow us
  860. // to specify the inclusion of the root, but CERT_CertChainFromCert() does.
  861. // Since CERT_CertChainFromCert() also includes the certificate itself,
  862. // we have to start at the issuing cert (to avoid duplicate certs
  863. // in the SignedData).
  864. if (chainMode == nsIX509Cert::CMS_CHAIN_MODE_CertChain ||
  865. chainMode == nsIX509Cert::CMS_CHAIN_MODE_CertChainWithRoot) {
  866. UniqueCERTCertificate issuerCert(
  867. CERT_FindCertIssuer(mCert.get(), PR_Now(), certUsageAnyCA));
  868. // the issuerCert of a self signed root is the cert itself,
  869. // so make sure we're not adding duplicates, again
  870. if (issuerCert && issuerCert != mCert) {
  871. bool includeRoot =
  872. (chainMode == nsIX509Cert::CMS_CHAIN_MODE_CertChainWithRoot);
  873. UniqueCERTCertificateList certChain(
  874. CERT_CertChainFromCert(issuerCert.get(), certUsageAnyCA, includeRoot));
  875. if (certChain) {
  876. if (NSS_CMSSignedData_AddCertList(sigd.get(), certChain.get())
  877. == SECSuccess) {
  878. Unused << certChain.release();
  879. }
  880. else {
  881. MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
  882. ("nsNSSCertificate::ExportAsCMS - can't add chain\n"));
  883. return NS_ERROR_FAILURE;
  884. }
  885. }
  886. else {
  887. // try to add the issuerCert, at least
  888. if (NSS_CMSSignedData_AddCertificate(sigd.get(), issuerCert.get())
  889. == SECSuccess) {
  890. Unused << issuerCert.release();
  891. }
  892. else {
  893. MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
  894. ("nsNSSCertificate::ExportAsCMS - can't add issuer cert\n"));
  895. return NS_ERROR_FAILURE;
  896. }
  897. }
  898. }
  899. }
  900. NSSCMSContentInfo* cinfo = NSS_CMSMessage_GetContentInfo(cmsg.get());
  901. if (NSS_CMSContentInfo_SetContent_SignedData(cmsg.get(), cinfo, sigd.get())
  902. == SECSuccess) {
  903. Unused << sigd.release();
  904. }
  905. else {
  906. MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
  907. ("nsNSSCertificate::ExportAsCMS - can't attach SignedData\n"));
  908. return NS_ERROR_FAILURE;
  909. }
  910. UniquePLArenaPool arena(PORT_NewArena(1024));
  911. if (!arena) {
  912. MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
  913. ("nsNSSCertificate::ExportAsCMS - out of memory\n"));
  914. return NS_ERROR_OUT_OF_MEMORY;
  915. }
  916. SECItem certP7 = { siBuffer, nullptr, 0 };
  917. NSSCMSEncoderContext* ecx = NSS_CMSEncoder_Start(cmsg.get(), nullptr, nullptr,
  918. &certP7, arena.get(), nullptr,
  919. nullptr, nullptr, nullptr,
  920. nullptr, nullptr);
  921. if (!ecx) {
  922. MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
  923. ("nsNSSCertificate::ExportAsCMS - can't create encoder context\n"));
  924. return NS_ERROR_FAILURE;
  925. }
  926. if (NSS_CMSEncoder_Finish(ecx) != SECSuccess) {
  927. MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
  928. ("nsNSSCertificate::ExportAsCMS - failed to add encoded data\n"));
  929. return NS_ERROR_FAILURE;
  930. }
  931. *aArray = (uint8_t*)moz_xmalloc(certP7.len);
  932. if (!*aArray)
  933. return NS_ERROR_OUT_OF_MEMORY;
  934. memcpy(*aArray, certP7.data, certP7.len);
  935. *aLength = certP7.len;
  936. return NS_OK;
  937. }
  938. CERTCertificate*
  939. nsNSSCertificate::GetCert()
  940. {
  941. nsNSSShutDownPreventionLock locker;
  942. if (isAlreadyShutDown())
  943. return nullptr;
  944. return (mCert) ? CERT_DupCertificate(mCert.get()) : nullptr;
  945. }
  946. NS_IMETHODIMP
  947. nsNSSCertificate::GetValidity(nsIX509CertValidity** aValidity)
  948. {
  949. nsNSSShutDownPreventionLock locker;
  950. if (isAlreadyShutDown())
  951. return NS_ERROR_NOT_AVAILABLE;
  952. NS_ENSURE_ARG(aValidity);
  953. if (!mCert) {
  954. return NS_ERROR_FAILURE;
  955. }
  956. nsCOMPtr<nsIX509CertValidity> validity = new nsX509CertValidity(mCert);
  957. validity.forget(aValidity);
  958. return NS_OK;
  959. }
  960. NS_IMETHODIMP
  961. nsNSSCertificate::GetASN1Structure(nsIASN1Object** aASN1Structure)
  962. {
  963. NS_ENSURE_ARG_POINTER(aASN1Structure);
  964. return CreateASN1Struct(aASN1Structure);
  965. }
  966. NS_IMETHODIMP
  967. nsNSSCertificate::Equals(nsIX509Cert* other, bool* result)
  968. {
  969. nsNSSShutDownPreventionLock locker;
  970. if (isAlreadyShutDown())
  971. return NS_ERROR_NOT_AVAILABLE;
  972. NS_ENSURE_ARG(other);
  973. NS_ENSURE_ARG(result);
  974. UniqueCERTCertificate cert(other->GetCert());
  975. *result = (mCert.get() == cert.get());
  976. return NS_OK;
  977. }
  978. namespace mozilla {
  979. // TODO(bug 1036065): It seems like we only construct CERTCertLists for the
  980. // purpose of constructing nsNSSCertLists, so maybe we should change this
  981. // function to output an nsNSSCertList instead.
  982. SECStatus
  983. ConstructCERTCertListFromReversedDERArray(
  984. const mozilla::pkix::DERArray& certArray,
  985. /*out*/ UniqueCERTCertList& certList)
  986. {
  987. certList = UniqueCERTCertList(CERT_NewCertList());
  988. if (!certList) {
  989. return SECFailure;
  990. }
  991. CERTCertDBHandle* certDB(CERT_GetDefaultCertDB()); // non-owning
  992. size_t numCerts = certArray.GetLength();
  993. for (size_t i = 0; i < numCerts; ++i) {
  994. SECItem certDER(UnsafeMapInputToSECItem(*certArray.GetDER(i)));
  995. UniqueCERTCertificate cert(CERT_NewTempCertificate(certDB, &certDER,
  996. nullptr, false, true));
  997. if (!cert) {
  998. return SECFailure;
  999. }
  1000. // certArray is ordered with the root first, but we want the resulting
  1001. // certList to have the root last.
  1002. if (CERT_AddCertToListHead(certList.get(), cert.get()) != SECSuccess) {
  1003. return SECFailure;
  1004. }
  1005. Unused << cert.release(); // cert is now owned by certList.
  1006. }
  1007. return SECSuccess;
  1008. }
  1009. } // namespace mozilla
  1010. NS_IMPL_CLASSINFO(nsNSSCertList,
  1011. nullptr,
  1012. // inferred from nsIX509Cert
  1013. nsIClassInfo::THREADSAFE,
  1014. NS_X509CERTLIST_CID)
  1015. NS_IMPL_ISUPPORTS_CI(nsNSSCertList,
  1016. nsIX509CertList,
  1017. nsISerializable)
  1018. nsNSSCertList::nsNSSCertList(UniqueCERTCertList certList,
  1019. const nsNSSShutDownPreventionLock& proofOfLock)
  1020. {
  1021. if (certList) {
  1022. mCertList = Move(certList);
  1023. } else {
  1024. mCertList = UniqueCERTCertList(CERT_NewCertList());
  1025. }
  1026. }
  1027. nsNSSCertList::nsNSSCertList()
  1028. {
  1029. mCertList = UniqueCERTCertList(CERT_NewCertList());
  1030. }
  1031. nsNSSCertList::~nsNSSCertList()
  1032. {
  1033. nsNSSShutDownPreventionLock locker;
  1034. if (isAlreadyShutDown()) {
  1035. return;
  1036. }
  1037. destructorSafeDestroyNSSReference();
  1038. shutdown(ShutdownCalledFrom::Object);
  1039. }
  1040. void nsNSSCertList::virtualDestroyNSSReference()
  1041. {
  1042. destructorSafeDestroyNSSReference();
  1043. }
  1044. void nsNSSCertList::destructorSafeDestroyNSSReference()
  1045. {
  1046. mCertList = nullptr;
  1047. }
  1048. NS_IMETHODIMP
  1049. nsNSSCertList::AddCert(nsIX509Cert* aCert)
  1050. {
  1051. if (!aCert) {
  1052. return NS_ERROR_INVALID_ARG;
  1053. }
  1054. nsNSSShutDownPreventionLock locker;
  1055. if (isAlreadyShutDown()) {
  1056. return NS_ERROR_NOT_AVAILABLE;
  1057. }
  1058. CERTCertificate* cert = aCert->GetCert();
  1059. if (!cert) {
  1060. NS_ERROR("Somehow got nullptr for mCertificate in nsNSSCertificate.");
  1061. return NS_ERROR_FAILURE;
  1062. }
  1063. if (!mCertList) {
  1064. NS_ERROR("Somehow got nullptr for mCertList in nsNSSCertList.");
  1065. return NS_ERROR_FAILURE;
  1066. }
  1067. // XXX: check return value!
  1068. CERT_AddCertToListTail(mCertList.get(), cert);
  1069. return NS_OK;
  1070. }
  1071. NS_IMETHODIMP
  1072. nsNSSCertList::DeleteCert(nsIX509Cert* aCert)
  1073. {
  1074. nsNSSShutDownPreventionLock locker;
  1075. if (isAlreadyShutDown()) {
  1076. return NS_ERROR_NOT_AVAILABLE;
  1077. }
  1078. CERTCertificate* cert = aCert->GetCert();
  1079. CERTCertListNode* node;
  1080. if (!cert) {
  1081. NS_ERROR("Somehow got nullptr for mCertificate in nsNSSCertificate.");
  1082. return NS_ERROR_FAILURE;
  1083. }
  1084. if (!mCertList) {
  1085. NS_ERROR("Somehow got nullptr for mCertList in nsNSSCertList.");
  1086. return NS_ERROR_FAILURE;
  1087. }
  1088. for (node = CERT_LIST_HEAD(mCertList.get());
  1089. !CERT_LIST_END(node, mCertList.get()); node = CERT_LIST_NEXT(node)) {
  1090. if (node->cert == cert) {
  1091. CERT_RemoveCertListNode(node);
  1092. return NS_OK;
  1093. }
  1094. }
  1095. return NS_OK; // XXX Should we fail if we couldn't find it?
  1096. }
  1097. UniqueCERTCertList
  1098. nsNSSCertList::DupCertList(const UniqueCERTCertList& certList,
  1099. const nsNSSShutDownPreventionLock& /*proofOfLock*/)
  1100. {
  1101. if (!certList) {
  1102. return nullptr;
  1103. }
  1104. UniqueCERTCertList newList(CERT_NewCertList());
  1105. if (!newList) {
  1106. return nullptr;
  1107. }
  1108. for (CERTCertListNode* node = CERT_LIST_HEAD(certList);
  1109. !CERT_LIST_END(node, certList);
  1110. node = CERT_LIST_NEXT(node)) {
  1111. UniqueCERTCertificate cert(CERT_DupCertificate(node->cert));
  1112. if (!cert) {
  1113. return nullptr;
  1114. }
  1115. if (CERT_AddCertToListTail(newList.get(), cert.get()) != SECSuccess) {
  1116. return nullptr;
  1117. }
  1118. Unused << cert.release(); // Ownership transferred to the cert list.
  1119. }
  1120. return newList;
  1121. }
  1122. CERTCertList*
  1123. nsNSSCertList::GetRawCertList()
  1124. {
  1125. // This function should only be called after acquiring a
  1126. // nsNSSShutDownPreventionLock. It's difficult to enforce this in code since
  1127. // this is an implementation of an XPCOM interface function (albeit a
  1128. // C++-only one), so we acquire the (reentrant) lock and check for shutdown
  1129. // ourselves here. At the moment it appears that only nsCertTree uses this
  1130. // function. When that gets removed and replaced by a more reasonable
  1131. // implementation of the certificate manager, this function can be removed.
  1132. nsNSSShutDownPreventionLock locker;
  1133. if (isAlreadyShutDown()) {
  1134. return nullptr;
  1135. }
  1136. return mCertList.get();
  1137. }
  1138. NS_IMETHODIMP
  1139. nsNSSCertList::Write(nsIObjectOutputStream* aStream)
  1140. {
  1141. nsNSSShutDownPreventionLock locker;
  1142. if (isAlreadyShutDown()) {
  1143. return NS_ERROR_NOT_AVAILABLE;
  1144. }
  1145. NS_ENSURE_STATE(mCertList);
  1146. nsresult rv = NS_OK;
  1147. // First, enumerate the certs to get the length of the list
  1148. uint32_t certListLen = 0;
  1149. CERTCertListNode* node = nullptr;
  1150. for (node = CERT_LIST_HEAD(mCertList);
  1151. !CERT_LIST_END(node, mCertList);
  1152. node = CERT_LIST_NEXT(node), ++certListLen) {
  1153. }
  1154. // Write the length of the list
  1155. rv = aStream->Write32(certListLen);
  1156. // Repeat the loop, and serialize each certificate
  1157. node = nullptr;
  1158. for (node = CERT_LIST_HEAD(mCertList);
  1159. !CERT_LIST_END(node, mCertList);
  1160. node = CERT_LIST_NEXT(node))
  1161. {
  1162. nsCOMPtr<nsIX509Cert> cert = nsNSSCertificate::Create(node->cert);
  1163. if (!cert) {
  1164. rv = NS_ERROR_OUT_OF_MEMORY;
  1165. break;
  1166. }
  1167. nsCOMPtr<nsISerializable> serializableCert = do_QueryInterface(cert);
  1168. rv = aStream->WriteCompoundObject(serializableCert, NS_GET_IID(nsIX509Cert), true);
  1169. if (NS_FAILED(rv)) {
  1170. break;
  1171. }
  1172. }
  1173. return rv;
  1174. }
  1175. NS_IMETHODIMP
  1176. nsNSSCertList::Read(nsIObjectInputStream* aStream)
  1177. {
  1178. nsNSSShutDownPreventionLock locker;
  1179. if (isAlreadyShutDown()) {
  1180. return NS_ERROR_NOT_AVAILABLE;
  1181. }
  1182. NS_ENSURE_STATE(mCertList);
  1183. nsresult rv = NS_OK;
  1184. uint32_t certListLen;
  1185. rv = aStream->Read32(&certListLen);
  1186. if (NS_FAILED(rv)) {
  1187. return rv;
  1188. }
  1189. for(uint32_t i = 0; i < certListLen; ++i) {
  1190. nsCOMPtr<nsISupports> certSupports;
  1191. rv = aStream->ReadObject(true, getter_AddRefs(certSupports));
  1192. if (NS_FAILED(rv)) {
  1193. return rv;
  1194. }
  1195. nsCOMPtr<nsIX509Cert> cert = do_QueryInterface(certSupports);
  1196. if (!cert) {
  1197. return NS_ERROR_UNEXPECTED;
  1198. }
  1199. rv = AddCert(cert);
  1200. if (NS_FAILED(rv)) {
  1201. return rv;
  1202. }
  1203. }
  1204. return NS_OK;
  1205. }
  1206. NS_IMETHODIMP
  1207. nsNSSCertList::GetEnumerator(nsISimpleEnumerator** _retval)
  1208. {
  1209. nsNSSShutDownPreventionLock locker;
  1210. if (isAlreadyShutDown()) {
  1211. return NS_ERROR_NOT_AVAILABLE;
  1212. }
  1213. if (!mCertList) {
  1214. return NS_ERROR_FAILURE;
  1215. }
  1216. nsCOMPtr<nsISimpleEnumerator> enumerator =
  1217. new nsNSSCertListEnumerator(mCertList, locker);
  1218. enumerator.forget(_retval);
  1219. return NS_OK;
  1220. }
  1221. NS_IMETHODIMP
  1222. nsNSSCertList::Equals(nsIX509CertList* other, bool* result)
  1223. {
  1224. nsNSSShutDownPreventionLock locker;
  1225. if (isAlreadyShutDown()) {
  1226. return NS_ERROR_NOT_AVAILABLE;
  1227. }
  1228. NS_ENSURE_ARG(result);
  1229. *result = true;
  1230. nsresult rv;
  1231. nsCOMPtr<nsISimpleEnumerator> selfEnumerator;
  1232. rv = GetEnumerator(getter_AddRefs(selfEnumerator));
  1233. if (NS_FAILED(rv)) {
  1234. return rv;
  1235. }
  1236. nsCOMPtr<nsISimpleEnumerator> otherEnumerator;
  1237. rv = other->GetEnumerator(getter_AddRefs(otherEnumerator));
  1238. if (NS_FAILED(rv)) {
  1239. return rv;
  1240. }
  1241. nsCOMPtr<nsISupports> selfSupports;
  1242. nsCOMPtr<nsISupports> otherSupports;
  1243. while (NS_SUCCEEDED(selfEnumerator->GetNext(getter_AddRefs(selfSupports)))) {
  1244. if (NS_SUCCEEDED(otherEnumerator->GetNext(getter_AddRefs(otherSupports)))) {
  1245. nsCOMPtr<nsIX509Cert> selfCert = do_QueryInterface(selfSupports);
  1246. nsCOMPtr<nsIX509Cert> otherCert = do_QueryInterface(otherSupports);
  1247. bool certsEqual = false;
  1248. rv = selfCert->Equals(otherCert, &certsEqual);
  1249. if (NS_FAILED(rv)) {
  1250. return rv;
  1251. }
  1252. if (!certsEqual) {
  1253. *result = false;
  1254. break;
  1255. }
  1256. } else {
  1257. // other is shorter than self
  1258. *result = false;
  1259. break;
  1260. }
  1261. }
  1262. // Make sure self is the same length as other
  1263. bool otherHasMore = false;
  1264. rv = otherEnumerator->HasMoreElements(&otherHasMore);
  1265. if (NS_FAILED(rv)) {
  1266. return rv;
  1267. }
  1268. if (otherHasMore) {
  1269. *result = false;
  1270. }
  1271. return NS_OK;
  1272. }
  1273. NS_IMPL_ISUPPORTS(nsNSSCertListEnumerator, nsISimpleEnumerator)
  1274. nsNSSCertListEnumerator::nsNSSCertListEnumerator(
  1275. const UniqueCERTCertList& certList,
  1276. const nsNSSShutDownPreventionLock& proofOfLock)
  1277. {
  1278. MOZ_ASSERT(certList);
  1279. mCertList = nsNSSCertList::DupCertList(certList, proofOfLock);
  1280. }
  1281. nsNSSCertListEnumerator::~nsNSSCertListEnumerator()
  1282. {
  1283. nsNSSShutDownPreventionLock locker;
  1284. if (isAlreadyShutDown()) {
  1285. return;
  1286. }
  1287. destructorSafeDestroyNSSReference();
  1288. shutdown(ShutdownCalledFrom::Object);
  1289. }
  1290. void nsNSSCertListEnumerator::virtualDestroyNSSReference()
  1291. {
  1292. destructorSafeDestroyNSSReference();
  1293. }
  1294. void nsNSSCertListEnumerator::destructorSafeDestroyNSSReference()
  1295. {
  1296. mCertList = nullptr;
  1297. }
  1298. NS_IMETHODIMP
  1299. nsNSSCertListEnumerator::HasMoreElements(bool* _retval)
  1300. {
  1301. nsNSSShutDownPreventionLock locker;
  1302. if (isAlreadyShutDown()) {
  1303. return NS_ERROR_NOT_AVAILABLE;
  1304. }
  1305. NS_ENSURE_TRUE(mCertList, NS_ERROR_FAILURE);
  1306. *_retval = !CERT_LIST_EMPTY(mCertList);
  1307. return NS_OK;
  1308. }
  1309. NS_IMETHODIMP
  1310. nsNSSCertListEnumerator::GetNext(nsISupports** _retval)
  1311. {
  1312. nsNSSShutDownPreventionLock locker;
  1313. if (isAlreadyShutDown()) {
  1314. return NS_ERROR_NOT_AVAILABLE;
  1315. }
  1316. NS_ENSURE_TRUE(mCertList, NS_ERROR_FAILURE);
  1317. CERTCertListNode* node = CERT_LIST_HEAD(mCertList);
  1318. if (CERT_LIST_END(node, mCertList)) {
  1319. return NS_ERROR_FAILURE;
  1320. }
  1321. nsCOMPtr<nsIX509Cert> nssCert = nsNSSCertificate::Create(node->cert);
  1322. if (!nssCert) {
  1323. return NS_ERROR_OUT_OF_MEMORY;
  1324. }
  1325. nssCert.forget(_retval);
  1326. CERT_RemoveCertListNode(node);
  1327. return NS_OK;
  1328. }
  1329. // NB: This serialization must match that of nsNSSCertificateFakeTransport.
  1330. NS_IMETHODIMP
  1331. nsNSSCertificate::Write(nsIObjectOutputStream* aStream)
  1332. {
  1333. NS_ENSURE_STATE(mCert);
  1334. // This field used to be the cached EV status, but it is no longer necessary.
  1335. nsresult rv = aStream->Write32(0);
  1336. if (NS_FAILED(rv)) {
  1337. return rv;
  1338. }
  1339. rv = aStream->Write32(mCert->derCert.len);
  1340. if (NS_FAILED(rv)) {
  1341. return rv;
  1342. }
  1343. return aStream->WriteByteArray(mCert->derCert.data, mCert->derCert.len);
  1344. }
  1345. NS_IMETHODIMP
  1346. nsNSSCertificate::Read(nsIObjectInputStream* aStream)
  1347. {
  1348. NS_ENSURE_STATE(!mCert);
  1349. // This field is no longer used.
  1350. uint32_t unusedCachedEVStatus;
  1351. nsresult rv = aStream->Read32(&unusedCachedEVStatus);
  1352. if (NS_FAILED(rv)) {
  1353. return rv;
  1354. }
  1355. uint32_t len;
  1356. rv = aStream->Read32(&len);
  1357. if (NS_FAILED(rv)) {
  1358. return rv;
  1359. }
  1360. nsXPIDLCString str;
  1361. rv = aStream->ReadBytes(len, getter_Copies(str));
  1362. if (NS_FAILED(rv)) {
  1363. return rv;
  1364. }
  1365. if (!InitFromDER(const_cast<char*>(str.get()), len)) {
  1366. return NS_ERROR_UNEXPECTED;
  1367. }
  1368. return NS_OK;
  1369. }
  1370. NS_IMETHODIMP
  1371. nsNSSCertificate::GetInterfaces(uint32_t* count, nsIID*** array)
  1372. {
  1373. *count = 0;
  1374. *array = nullptr;
  1375. return NS_OK;
  1376. }
  1377. NS_IMETHODIMP
  1378. nsNSSCertificate::GetScriptableHelper(nsIXPCScriptable** _retval)
  1379. {
  1380. *_retval = nullptr;
  1381. return NS_OK;
  1382. }
  1383. NS_IMETHODIMP
  1384. nsNSSCertificate::GetContractID(char** aContractID)
  1385. {
  1386. *aContractID = nullptr;
  1387. return NS_OK;
  1388. }
  1389. NS_IMETHODIMP
  1390. nsNSSCertificate::GetClassDescription(char** aClassDescription)
  1391. {
  1392. *aClassDescription = nullptr;
  1393. return NS_OK;
  1394. }
  1395. NS_IMETHODIMP
  1396. nsNSSCertificate::GetClassID(nsCID** aClassID)
  1397. {
  1398. *aClassID = (nsCID*) moz_xmalloc(sizeof(nsCID));
  1399. if (!*aClassID)
  1400. return NS_ERROR_OUT_OF_MEMORY;
  1401. return GetClassIDNoAlloc(*aClassID);
  1402. }
  1403. NS_IMETHODIMP
  1404. nsNSSCertificate::GetFlags(uint32_t* aFlags)
  1405. {
  1406. *aFlags = nsIClassInfo::THREADSAFE;
  1407. return NS_OK;
  1408. }
  1409. NS_IMETHODIMP
  1410. nsNSSCertificate::GetClassIDNoAlloc(nsCID* aClassIDNoAlloc)
  1411. {
  1412. static NS_DEFINE_CID(kNSSCertificateCID, NS_X509CERT_CID);
  1413. *aClassIDNoAlloc = kNSSCertificateCID;
  1414. return NS_OK;
  1415. }