nsNSSCertHelper.cpp 62 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  4. #include "nsNSSCertHelper.h"
  5. #include <algorithm>
  6. #include "ScopedNSSTypes.h"
  7. #include "mozilla/Casting.h"
  8. #include "mozilla/NotNull.h"
  9. #include "mozilla/Sprintf.h"
  10. #include "mozilla/UniquePtr.h"
  11. #include "mozilla/net/DNS.h"
  12. #include "nsCOMPtr.h"
  13. #include "nsComponentManagerUtils.h"
  14. #include "nsDateTimeFormatCID.h"
  15. #include "nsIDateTimeFormat.h"
  16. #include "nsNSSASN1Object.h"
  17. #include "nsNSSCertTrust.h"
  18. #include "nsNSSCertValidity.h"
  19. #include "nsNSSCertificate.h"
  20. #include "nsNSSComponent.h"
  21. #include "nsServiceManagerUtils.h"
  22. #include "prerror.h"
  23. #include "secder.h"
  24. using namespace mozilla;
  25. /* Object Identifier constants */
  26. #define CONST_OID static const unsigned char
  27. #define MICROSOFT_OID 0x2b, 0x6, 0x1, 0x4, 0x1, 0x82, 0x37
  28. #define PKIX_OID 0x2b, 0x6, 0x01, 0x05, 0x05, 0x07
  29. CONST_OID msCertExtCerttype[] = { MICROSOFT_OID, 20, 2};
  30. CONST_OID msNTPrincipalName[] = { MICROSOFT_OID, 20, 2, 3 };
  31. CONST_OID msCertsrvCAVersion[] = { MICROSOFT_OID, 21, 1 };
  32. CONST_OID msNTDSReplication[] = { MICROSOFT_OID, 25, 1 };
  33. CONST_OID pkixLogotype[] = { PKIX_OID, 1, 12 };
  34. #define OI(x) { siDEROID, (unsigned char *)x, sizeof x }
  35. #define OD(oid,desc,mech,ext) {OI(oid), SEC_OID_UNKNOWN, desc, mech, ext}
  36. #define SEC_OID(tag) more_oids[tag].offset
  37. static SECOidData more_oids[] = {
  38. /* Microsoft OIDs */
  39. #define MS_CERT_EXT_CERTTYPE 0
  40. OD( msCertExtCerttype,
  41. "Microsoft Certificate Template Name",
  42. CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION ),
  43. #define MS_NT_PRINCIPAL_NAME 1
  44. OD( msNTPrincipalName,
  45. "Microsoft Principal Name",
  46. CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION ),
  47. #define MS_CERTSERV_CA_VERSION 2
  48. OD( msCertsrvCAVersion,
  49. "Microsoft CA Version",
  50. CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION ),
  51. #define MS_NTDS_REPLICATION 3
  52. OD( msNTDSReplication,
  53. "Microsoft Domain GUID",
  54. CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION ),
  55. #define PKIX_LOGOTYPE 4
  56. OD( pkixLogotype,
  57. "Logotype",
  58. CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION ),
  59. };
  60. static const unsigned int numOids = (sizeof more_oids) / (sizeof more_oids[0]);
  61. static nsresult
  62. ProcessVersion(SECItem* versionItem, nsINSSComponent* nssComponent,
  63. nsIASN1PrintableItem** retItem)
  64. {
  65. nsAutoString text;
  66. nssComponent->GetPIPNSSBundleString("CertDumpVersion", text);
  67. nsCOMPtr<nsIASN1PrintableItem> printableItem = new nsNSSASN1PrintableItem();
  68. nsresult rv = printableItem->SetDisplayName(text);
  69. if (NS_FAILED(rv)) {
  70. return rv;
  71. }
  72. // Now to figure out what version this certificate is.
  73. unsigned int version;
  74. if (versionItem->data) {
  75. // Filter out totally bogus version values/encodings.
  76. if (versionItem->len != 1) {
  77. return NS_ERROR_FAILURE;
  78. }
  79. version = *BitwiseCast<uint8_t*, unsigned char*>(versionItem->data);
  80. } else {
  81. // If there is no version present in the cert, then RFC 5280 says we
  82. // default to v1 (0).
  83. version = 0;
  84. }
  85. // A value of n actually corresponds to version n + 1
  86. nsAutoString versionString;
  87. versionString.AppendInt(version + 1);
  88. const char16_t* params[1] = { versionString.get() };
  89. rv = nssComponent->PIPBundleFormatStringFromName("CertDumpVersionValue",
  90. params,
  91. MOZ_ARRAY_LENGTH(params),
  92. text);
  93. if (NS_FAILED(rv)) {
  94. return rv;
  95. }
  96. rv = printableItem->SetDisplayValue(text);
  97. if (NS_FAILED(rv)) {
  98. return rv;
  99. }
  100. printableItem.forget(retItem);
  101. return NS_OK;
  102. }
  103. static nsresult
  104. ProcessSerialNumberDER(const SECItem& serialItem,
  105. NotNull<nsINSSComponent*> nssComponent,
  106. /*out*/ nsCOMPtr<nsIASN1PrintableItem>& retItem)
  107. {
  108. nsAutoString text;
  109. nsresult rv = nssComponent->GetPIPNSSBundleString("CertDumpSerialNo", text);
  110. if (NS_FAILED(rv)) {
  111. return rv;
  112. }
  113. nsCOMPtr<nsIASN1PrintableItem> printableItem = new nsNSSASN1PrintableItem();
  114. rv = printableItem->SetDisplayName(text);
  115. if (NS_FAILED(rv)) {
  116. return rv;
  117. }
  118. UniquePORTString serialNumber(
  119. CERT_Hexify(const_cast<SECItem*>(&serialItem), 1));
  120. if (!serialNumber) {
  121. return NS_ERROR_OUT_OF_MEMORY;
  122. }
  123. rv = printableItem->SetDisplayValue(NS_ConvertASCIItoUTF16(serialNumber.get()));
  124. if (NS_FAILED(rv)) {
  125. return rv;
  126. }
  127. retItem = printableItem.forget();
  128. return NS_OK;
  129. }
  130. static nsresult
  131. GetDefaultOIDFormat(SECItem *oid,
  132. nsINSSComponent *nssComponent,
  133. nsAString &outString,
  134. char separator)
  135. {
  136. outString.Truncate();
  137. int invalidCount = 0;
  138. unsigned int i;
  139. unsigned long val = 0;
  140. bool invalid = false;
  141. bool first = true;
  142. val = 0;
  143. for (i = 0; i < oid->len; ++i) {
  144. // In this loop, we have to parse a DER formatted
  145. // If the first bit is a 1, then the integer is
  146. // represented by more than one byte. If the
  147. // first bit is set then we continue on and add
  148. // the values of the later bytes until we get
  149. // a byte without the first bit set.
  150. unsigned long j;
  151. j = oid->data[i];
  152. val = (val << 7) | (j & 0x7f);
  153. if (j & 0x80) {
  154. // - If val is 0 in this block, the OID number particle starts with 0x80
  155. // what is specified as an invalid formating.
  156. // - If val is larger then 2^32-7, on next left shift by 7 we will loose
  157. // the most significant bits, this OID number particle cannot be read
  158. // by our implementation.
  159. // - If the first bit is set while this is the last component of the OID
  160. // we are also in an invalid state.
  161. if (val == 0 || (val >= (1 << (32-7))) || (i == oid->len-1)) {
  162. invalid = true;
  163. }
  164. if (i < oid->len-1)
  165. continue;
  166. }
  167. if (!invalid) {
  168. if (first) {
  169. unsigned long one = std::min(val/40, 2UL); // never > 2
  170. unsigned long two = val - (one * 40);
  171. outString.AppendPrintf("%lu%c%lu", one, separator, two);
  172. }
  173. else {
  174. outString.AppendPrintf("%c%lu", separator, val);
  175. }
  176. }
  177. else {
  178. if (!first) {
  179. outString.AppendPrintf("%c", separator);
  180. }
  181. nsAutoString unknownText;
  182. nssComponent->GetPIPNSSBundleString("CertUnknown",
  183. unknownText);
  184. outString.Append(unknownText);
  185. if (++invalidCount > 3) {
  186. // Allow only 3 occurences of Unknown in OID display string to
  187. // prevent bloat.
  188. break;
  189. }
  190. }
  191. val = 0;
  192. invalid = false;
  193. first = false;
  194. }
  195. return NS_OK;
  196. }
  197. static nsresult
  198. GetOIDText(SECItem *oid, nsINSSComponent *nssComponent, nsAString &text)
  199. {
  200. nsresult rv;
  201. SECOidTag oidTag = SECOID_FindOIDTag(oid);
  202. const char *bundlekey = 0;
  203. switch (oidTag) {
  204. case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
  205. bundlekey = "CertDumpMD2WithRSA";
  206. break;
  207. case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
  208. bundlekey = "CertDumpMD5WithRSA";
  209. break;
  210. case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
  211. bundlekey = "CertDumpSHA1WithRSA";
  212. break;
  213. case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
  214. bundlekey = "CertDumpSHA256WithRSA";
  215. break;
  216. case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
  217. bundlekey = "CertDumpSHA384WithRSA";
  218. break;
  219. case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
  220. bundlekey = "CertDumpSHA512WithRSA";
  221. break;
  222. case SEC_OID_PKCS1_RSA_ENCRYPTION:
  223. bundlekey = "CertDumpRSAEncr";
  224. break;
  225. case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
  226. bundlekey = "CertDumpRSAPSSSignature";
  227. break;
  228. case SEC_OID_AVA_COUNTRY_NAME:
  229. bundlekey = "CertDumpAVACountry";
  230. break;
  231. case SEC_OID_AVA_COMMON_NAME:
  232. bundlekey = "CertDumpAVACN";
  233. break;
  234. case SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME:
  235. bundlekey = "CertDumpAVAOU";
  236. break;
  237. case SEC_OID_AVA_ORGANIZATION_NAME:
  238. bundlekey = "CertDumpAVAOrg";
  239. break;
  240. case SEC_OID_AVA_LOCALITY:
  241. bundlekey = "CertDumpAVALocality";
  242. break;
  243. case SEC_OID_AVA_DN_QUALIFIER:
  244. bundlekey = "CertDumpAVADN";
  245. break;
  246. case SEC_OID_AVA_DC:
  247. bundlekey = "CertDumpAVADC";
  248. break;
  249. case SEC_OID_AVA_STATE_OR_PROVINCE:
  250. bundlekey = "CertDumpAVAState";
  251. break;
  252. case SEC_OID_AVA_SURNAME:
  253. bundlekey = "CertDumpSurname";
  254. break;
  255. case SEC_OID_AVA_GIVEN_NAME:
  256. bundlekey = "CertDumpGivenName";
  257. break;
  258. case SEC_OID_X509_SUBJECT_DIRECTORY_ATTR:
  259. bundlekey = "CertDumpSubjectDirectoryAttr";
  260. break;
  261. case SEC_OID_X509_SUBJECT_KEY_ID:
  262. bundlekey = "CertDumpSubjectKeyID";
  263. break;
  264. case SEC_OID_X509_KEY_USAGE:
  265. bundlekey = "CertDumpKeyUsage";
  266. break;
  267. case SEC_OID_X509_SUBJECT_ALT_NAME:
  268. bundlekey = "CertDumpSubjectAltName";
  269. break;
  270. case SEC_OID_X509_ISSUER_ALT_NAME:
  271. bundlekey = "CertDumpIssuerAltName";
  272. break;
  273. case SEC_OID_X509_BASIC_CONSTRAINTS:
  274. bundlekey = "CertDumpBasicConstraints";
  275. break;
  276. case SEC_OID_X509_NAME_CONSTRAINTS:
  277. bundlekey = "CertDumpNameConstraints";
  278. break;
  279. case SEC_OID_X509_CRL_DIST_POINTS:
  280. bundlekey = "CertDumpCrlDistPoints";
  281. break;
  282. case SEC_OID_X509_CERTIFICATE_POLICIES:
  283. bundlekey = "CertDumpCertPolicies";
  284. break;
  285. case SEC_OID_X509_POLICY_MAPPINGS:
  286. bundlekey = "CertDumpPolicyMappings";
  287. break;
  288. case SEC_OID_X509_POLICY_CONSTRAINTS:
  289. bundlekey = "CertDumpPolicyConstraints";
  290. break;
  291. case SEC_OID_X509_AUTH_KEY_ID:
  292. bundlekey = "CertDumpAuthKeyID";
  293. break;
  294. case SEC_OID_X509_EXT_KEY_USAGE:
  295. bundlekey = "CertDumpExtKeyUsage";
  296. break;
  297. case SEC_OID_X509_AUTH_INFO_ACCESS:
  298. bundlekey = "CertDumpAuthInfoAccess";
  299. break;
  300. case SEC_OID_ANSIX9_DSA_SIGNATURE:
  301. bundlekey = "CertDumpAnsiX9DsaSignature";
  302. break;
  303. case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST:
  304. bundlekey = "CertDumpAnsiX9DsaSignatureWithSha1";
  305. break;
  306. case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
  307. bundlekey = "CertDumpAnsiX962ECDsaSignatureWithSha1";
  308. break;
  309. case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE:
  310. bundlekey = "CertDumpAnsiX962ECDsaSignatureWithSha224";
  311. break;
  312. case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE:
  313. bundlekey = "CertDumpAnsiX962ECDsaSignatureWithSha256";
  314. break;
  315. case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE:
  316. bundlekey = "CertDumpAnsiX962ECDsaSignatureWithSha384";
  317. break;
  318. case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE:
  319. bundlekey = "CertDumpAnsiX962ECDsaSignatureWithSha512";
  320. break;
  321. case SEC_OID_RFC1274_UID:
  322. bundlekey = "CertDumpUserID";
  323. break;
  324. case SEC_OID_PKCS9_EMAIL_ADDRESS:
  325. bundlekey = "CertDumpPK9Email";
  326. break;
  327. case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
  328. bundlekey = "CertDumpECPublicKey";
  329. break;
  330. /* ANSI X9.62 named elliptic curves (prime field) */
  331. case SEC_OID_ANSIX962_EC_PRIME192V1:
  332. /* same as SEC_OID_SECG_EC_SECP192r1 */
  333. bundlekey = "CertDumpECprime192v1";
  334. break;
  335. case SEC_OID_ANSIX962_EC_PRIME192V2:
  336. bundlekey = "CertDumpECprime192v2";
  337. break;
  338. case SEC_OID_ANSIX962_EC_PRIME192V3:
  339. bundlekey = "CertDumpECprime192v3";
  340. break;
  341. case SEC_OID_ANSIX962_EC_PRIME239V1:
  342. bundlekey = "CertDumpECprime239v1";
  343. break;
  344. case SEC_OID_ANSIX962_EC_PRIME239V2:
  345. bundlekey = "CertDumpECprime239v2";
  346. break;
  347. case SEC_OID_ANSIX962_EC_PRIME239V3:
  348. bundlekey = "CertDumpECprime239v3";
  349. break;
  350. case SEC_OID_ANSIX962_EC_PRIME256V1:
  351. /* same as SEC_OID_SECG_EC_SECP256r1 */
  352. bundlekey = "CertDumpECprime256v1";
  353. break;
  354. /* SECG named elliptic curves (prime field) */
  355. case SEC_OID_SECG_EC_SECP112R1:
  356. bundlekey = "CertDumpECsecp112r1";
  357. break;
  358. case SEC_OID_SECG_EC_SECP112R2:
  359. bundlekey = "CertDumpECsecp112r2";
  360. break;
  361. case SEC_OID_SECG_EC_SECP128R1:
  362. bundlekey = "CertDumpECsecp128r1";
  363. break;
  364. case SEC_OID_SECG_EC_SECP128R2:
  365. bundlekey = "CertDumpECsecp128r2";
  366. break;
  367. case SEC_OID_SECG_EC_SECP160K1:
  368. bundlekey = "CertDumpECsecp160k1";
  369. break;
  370. case SEC_OID_SECG_EC_SECP160R1:
  371. bundlekey = "CertDumpECsecp160r1";
  372. break;
  373. case SEC_OID_SECG_EC_SECP160R2:
  374. bundlekey = "CertDumpECsecp160r2";
  375. break;
  376. case SEC_OID_SECG_EC_SECP192K1:
  377. bundlekey = "CertDumpECsecp192k1";
  378. break;
  379. case SEC_OID_SECG_EC_SECP224K1:
  380. bundlekey = "CertDumpECsecp224k1";
  381. break;
  382. case SEC_OID_SECG_EC_SECP224R1:
  383. bundlekey = "CertDumpECsecp224r1";
  384. break;
  385. case SEC_OID_SECG_EC_SECP256K1:
  386. bundlekey = "CertDumpECsecp256k1";
  387. break;
  388. case SEC_OID_SECG_EC_SECP384R1:
  389. bundlekey = "CertDumpECsecp384r1";
  390. break;
  391. case SEC_OID_SECG_EC_SECP521R1:
  392. bundlekey = "CertDumpECsecp521r1";
  393. break;
  394. /* ANSI X9.62 named elliptic curves (characteristic two field) */
  395. case SEC_OID_ANSIX962_EC_C2PNB163V1:
  396. bundlekey = "CertDumpECc2pnb163v1";
  397. break;
  398. case SEC_OID_ANSIX962_EC_C2PNB163V2:
  399. bundlekey = "CertDumpECc2pnb163v2";
  400. break;
  401. case SEC_OID_ANSIX962_EC_C2PNB163V3:
  402. bundlekey = "CertDumpECc2pnb163v3";
  403. break;
  404. case SEC_OID_ANSIX962_EC_C2PNB176V1:
  405. bundlekey = "CertDumpECc2pnb176v1";
  406. break;
  407. case SEC_OID_ANSIX962_EC_C2TNB191V1:
  408. bundlekey = "CertDumpECc2tnb191v1";
  409. break;
  410. case SEC_OID_ANSIX962_EC_C2TNB191V2:
  411. bundlekey = "CertDumpECc2tnb191v2";
  412. break;
  413. case SEC_OID_ANSIX962_EC_C2TNB191V3:
  414. bundlekey = "CertDumpECc2tnb191v3";
  415. break;
  416. case SEC_OID_ANSIX962_EC_C2ONB191V4:
  417. bundlekey = "CertDumpECc2onb191v4";
  418. break;
  419. case SEC_OID_ANSIX962_EC_C2ONB191V5:
  420. bundlekey = "CertDumpECc2onb191v5";
  421. break;
  422. case SEC_OID_ANSIX962_EC_C2PNB208W1:
  423. bundlekey = "CertDumpECc2pnb208w1";
  424. break;
  425. case SEC_OID_ANSIX962_EC_C2TNB239V1:
  426. bundlekey = "CertDumpECc2tnb239v1";
  427. break;
  428. case SEC_OID_ANSIX962_EC_C2TNB239V2:
  429. bundlekey = "CertDumpECc2tnb239v2";
  430. break;
  431. case SEC_OID_ANSIX962_EC_C2TNB239V3:
  432. bundlekey = "CertDumpECc2tnb239v3";
  433. break;
  434. case SEC_OID_ANSIX962_EC_C2ONB239V4:
  435. bundlekey = "CertDumpECc2onb239v4";
  436. break;
  437. case SEC_OID_ANSIX962_EC_C2ONB239V5:
  438. bundlekey = "CertDumpECc2onb239v5";
  439. break;
  440. case SEC_OID_ANSIX962_EC_C2PNB272W1:
  441. bundlekey = "CertDumpECc2pnb272w1";
  442. break;
  443. case SEC_OID_ANSIX962_EC_C2PNB304W1:
  444. bundlekey = "CertDumpECc2pnb304w1";
  445. break;
  446. case SEC_OID_ANSIX962_EC_C2TNB359V1:
  447. bundlekey = "CertDumpECc2tnb359v1";
  448. break;
  449. case SEC_OID_ANSIX962_EC_C2PNB368W1:
  450. bundlekey = "CertDumpECc2pnb368w1";
  451. break;
  452. case SEC_OID_ANSIX962_EC_C2TNB431R1:
  453. bundlekey = "CertDumpECc2tnb431r1";
  454. break;
  455. /* SECG named elliptic curves (characteristic two field) */
  456. case SEC_OID_SECG_EC_SECT113R1:
  457. bundlekey = "CertDumpECsect113r1";
  458. break;
  459. case SEC_OID_SECG_EC_SECT113R2:
  460. bundlekey = "CertDumpECsect113r2";
  461. break;
  462. case SEC_OID_SECG_EC_SECT131R1:
  463. bundlekey = "CertDumpECsect131r1";
  464. break;
  465. case SEC_OID_SECG_EC_SECT131R2:
  466. bundlekey = "CertDumpECsect131r2";
  467. break;
  468. case SEC_OID_SECG_EC_SECT163K1:
  469. bundlekey = "CertDumpECsect163k1";
  470. break;
  471. case SEC_OID_SECG_EC_SECT163R1:
  472. bundlekey = "CertDumpECsect163r1";
  473. break;
  474. case SEC_OID_SECG_EC_SECT163R2:
  475. bundlekey = "CertDumpECsect163r2";
  476. break;
  477. case SEC_OID_SECG_EC_SECT193R1:
  478. bundlekey = "CertDumpECsect193r1";
  479. break;
  480. case SEC_OID_SECG_EC_SECT193R2:
  481. bundlekey = "CertDumpECsect193r2";
  482. break;
  483. case SEC_OID_SECG_EC_SECT233K1:
  484. bundlekey = "CertDumpECsect233k1";
  485. break;
  486. case SEC_OID_SECG_EC_SECT233R1:
  487. bundlekey = "CertDumpECsect233r1";
  488. break;
  489. case SEC_OID_SECG_EC_SECT239K1:
  490. bundlekey = "CertDumpECsect239k1";
  491. break;
  492. case SEC_OID_SECG_EC_SECT283K1:
  493. bundlekey = "CertDumpECsect283k1";
  494. break;
  495. case SEC_OID_SECG_EC_SECT283R1:
  496. bundlekey = "CertDumpECsect283r1";
  497. break;
  498. case SEC_OID_SECG_EC_SECT409K1:
  499. bundlekey = "CertDumpECsect409k1";
  500. break;
  501. case SEC_OID_SECG_EC_SECT409R1:
  502. bundlekey = "CertDumpECsect409r1";
  503. break;
  504. case SEC_OID_SECG_EC_SECT571K1:
  505. bundlekey = "CertDumpECsect571k1";
  506. break;
  507. case SEC_OID_SECG_EC_SECT571R1:
  508. bundlekey = "CertDumpECsect571r1";
  509. break;
  510. default:
  511. if (oidTag == SEC_OID(MS_CERT_EXT_CERTTYPE)) {
  512. bundlekey = "CertDumpMSCerttype";
  513. break;
  514. }
  515. if (oidTag == SEC_OID(MS_CERTSERV_CA_VERSION)) {
  516. bundlekey = "CertDumpMSCAVersion";
  517. break;
  518. }
  519. if (oidTag == SEC_OID(PKIX_LOGOTYPE)) {
  520. bundlekey = "CertDumpLogotype";
  521. break;
  522. }
  523. /* fallthrough */
  524. }
  525. if (bundlekey) {
  526. rv = nssComponent->GetPIPNSSBundleString(bundlekey, text);
  527. } else {
  528. nsAutoString text2;
  529. rv = GetDefaultOIDFormat(oid, nssComponent, text2, ' ');
  530. if (NS_FAILED(rv))
  531. return rv;
  532. const char16_t *params[1] = {text2.get()};
  533. rv = nssComponent->PIPBundleFormatStringFromName("CertDumpDefOID",
  534. params, 1, text);
  535. }
  536. return rv;
  537. }
  538. #define SEPARATOR "\n"
  539. static nsresult
  540. ProcessRawBytes(nsINSSComponent *nssComponent, SECItem *data,
  541. nsAString &text, bool wantHeader = true)
  542. {
  543. // This function is used to display some DER bytes
  544. // that we have not added support for decoding.
  545. // If it's short, let's display as an integer, no size header.
  546. if (data->len <= 4) {
  547. int i_pv = DER_GetInteger(data);
  548. nsAutoString value;
  549. value.AppendInt(i_pv);
  550. text.Append(value);
  551. text.AppendLiteral(SEPARATOR);
  552. return NS_OK;
  553. }
  554. // Else produce a hex dump.
  555. if (wantHeader) {
  556. nsAutoString bytelen, bitlen;
  557. bytelen.AppendInt(data->len);
  558. bitlen.AppendInt(data->len*8);
  559. const char16_t *params[2] = {bytelen.get(), bitlen.get()};
  560. nsresult rv = nssComponent->PIPBundleFormatStringFromName("CertDumpRawBytesHeader",
  561. params, 2, text);
  562. if (NS_FAILED(rv))
  563. return rv;
  564. text.AppendLiteral(SEPARATOR);
  565. }
  566. // This prints the value of the byte out into a
  567. // string that can later be displayed as a byte
  568. // string. We place a new line after 24 bytes
  569. // to break up extermaly long sequence of bytes.
  570. uint32_t i;
  571. char buffer[5];
  572. for (i=0; i<data->len; i++) {
  573. SprintfLiteral(buffer, "%02x ", data->data[i]);
  574. AppendASCIItoUTF16(buffer, text);
  575. if ((i+1)%16 == 0) {
  576. text.AppendLiteral(SEPARATOR);
  577. }
  578. }
  579. return NS_OK;
  580. }
  581. /**
  582. * Appends a pipnss bundle string to the given string.
  583. *
  584. * @param nssComponent For accessing the string bundle.
  585. * @param bundleKey Key for the string to append.
  586. * @param currentText The text to append to, using |SEPARATOR| as the separator.
  587. */
  588. template<size_t N>
  589. void AppendBundleString(const NotNull<nsINSSComponent*>& nssComponent,
  590. const char (&bundleKey)[N],
  591. /*in/out*/ nsAString& currentText)
  592. {
  593. nsAutoString bundleString;
  594. nsresult rv = nssComponent->GetPIPNSSBundleString(bundleKey, bundleString);
  595. if (NS_FAILED(rv)) {
  596. return;
  597. }
  598. currentText.Append(bundleString);
  599. currentText.AppendLiteral(SEPARATOR);
  600. }
  601. static nsresult
  602. ProcessKeyUsageExtension(SECItem *extData, nsAString &text,
  603. nsINSSComponent *nssComponent)
  604. {
  605. MOZ_ASSERT(extData);
  606. MOZ_ASSERT(nssComponent);
  607. NS_ENSURE_ARG(extData);
  608. NS_ENSURE_ARG(nssComponent);
  609. NotNull<nsINSSComponent*> wrappedNSSComponent = WrapNotNull(nssComponent);
  610. ScopedAutoSECItem decoded;
  611. if (SEC_ASN1DecodeItem(nullptr, &decoded, SEC_ASN1_GET(SEC_BitStringTemplate),
  612. extData) != SECSuccess) {
  613. AppendBundleString(wrappedNSSComponent, "CertDumpExtensionFailure", text);
  614. return NS_OK;
  615. }
  616. unsigned char keyUsage = 0;
  617. if (decoded.len) {
  618. keyUsage = decoded.data[0];
  619. }
  620. if (keyUsage & KU_DIGITAL_SIGNATURE) {
  621. AppendBundleString(wrappedNSSComponent, "CertDumpKUSign", text);
  622. }
  623. if (keyUsage & KU_NON_REPUDIATION) {
  624. AppendBundleString(wrappedNSSComponent, "CertDumpKUNonRep", text);
  625. }
  626. if (keyUsage & KU_KEY_ENCIPHERMENT) {
  627. AppendBundleString(wrappedNSSComponent, "CertDumpKUEnc", text);
  628. }
  629. if (keyUsage & KU_DATA_ENCIPHERMENT) {
  630. AppendBundleString(wrappedNSSComponent, "CertDumpKUDEnc", text);
  631. }
  632. if (keyUsage & KU_KEY_AGREEMENT) {
  633. AppendBundleString(wrappedNSSComponent, "CertDumpKUKA", text);
  634. }
  635. if (keyUsage & KU_KEY_CERT_SIGN) {
  636. AppendBundleString(wrappedNSSComponent, "CertDumpKUCertSign", text);
  637. }
  638. if (keyUsage & KU_CRL_SIGN) {
  639. AppendBundleString(wrappedNSSComponent, "CertDumpKUCRLSigner", text);
  640. }
  641. return NS_OK;
  642. }
  643. static nsresult
  644. ProcessBasicConstraints(SECItem *extData,
  645. nsAString &text,
  646. nsINSSComponent *nssComponent)
  647. {
  648. nsAutoString local;
  649. CERTBasicConstraints value;
  650. SECStatus rv;
  651. nsresult rv2;
  652. value.pathLenConstraint = -1;
  653. rv = CERT_DecodeBasicConstraintValue (&value, extData);
  654. if (rv != SECSuccess) {
  655. ProcessRawBytes(nssComponent, extData, text);
  656. return NS_OK;
  657. }
  658. if (value.isCA)
  659. rv2 = nssComponent->GetPIPNSSBundleString("CertDumpIsCA", local);
  660. else
  661. rv2 = nssComponent->GetPIPNSSBundleString("CertDumpIsNotCA", local);
  662. if (NS_FAILED(rv2))
  663. return rv2;
  664. text.Append(local.get());
  665. if (value.pathLenConstraint != -1) {
  666. nsAutoString depth;
  667. if (value.pathLenConstraint == CERT_UNLIMITED_PATH_CONSTRAINT)
  668. nssComponent->GetPIPNSSBundleString("CertDumpPathLenUnlimited", depth);
  669. else
  670. depth.AppendInt(value.pathLenConstraint);
  671. const char16_t *params[1] = {depth.get()};
  672. rv2 = nssComponent->PIPBundleFormatStringFromName("CertDumpPathLen",
  673. params, 1, local);
  674. if (NS_FAILED(rv2))
  675. return rv2;
  676. text.AppendLiteral(SEPARATOR);
  677. text.Append(local.get());
  678. }
  679. return NS_OK;
  680. }
  681. static nsresult
  682. ProcessExtKeyUsage(SECItem *extData,
  683. nsAString &text,
  684. nsINSSComponent *nssComponent)
  685. {
  686. nsAutoString local;
  687. SECItem **oids;
  688. SECItem *oid;
  689. nsresult rv;
  690. UniqueCERTOidSequence extKeyUsage(CERT_DecodeOidSequence(extData));
  691. if (!extKeyUsage) {
  692. return NS_ERROR_FAILURE;
  693. }
  694. oids = extKeyUsage->oids;
  695. while (oids && *oids) {
  696. // For each OID, try to find a bundle string
  697. // of the form CertDumpEKU_<underlined-OID>
  698. nsAutoString oidname;
  699. oid = *oids;
  700. rv = GetDefaultOIDFormat(oid, nssComponent, oidname, '_');
  701. if (NS_FAILED(rv))
  702. return rv;
  703. nsAutoString bundlekey = NS_LITERAL_STRING("CertDumpEKU_")+ oidname;
  704. NS_ConvertUTF16toUTF8 bk_ascii(bundlekey);
  705. rv = nssComponent->GetPIPNSSBundleString(bk_ascii.get(), local);
  706. nsresult rv2 = GetDefaultOIDFormat(oid, nssComponent, oidname, '.');
  707. if (NS_FAILED(rv2))
  708. return rv2;
  709. if (NS_SUCCEEDED(rv)) {
  710. // display name and OID in parentheses
  711. text.Append(local);
  712. text.AppendLiteral(" (");
  713. text.Append(oidname);
  714. text.Append(')');
  715. } else
  716. // If there is no bundle string, just display the OID itself
  717. text.Append(oidname);
  718. text.AppendLiteral(SEPARATOR);
  719. oids++;
  720. }
  721. return NS_OK;
  722. }
  723. static nsresult
  724. ProcessRDN(CERTRDN* rdn, nsAString &finalString, nsINSSComponent *nssComponent)
  725. {
  726. nsresult rv;
  727. CERTAVA** avas;
  728. CERTAVA* ava;
  729. nsString avavalue;
  730. nsString type;
  731. nsAutoString temp;
  732. const char16_t *params[2];
  733. avas = rdn->avas;
  734. while ((ava = *avas++) != 0) {
  735. rv = GetOIDText(&ava->type, nssComponent, type);
  736. if (NS_FAILED(rv)) {
  737. return rv;
  738. }
  739. //This function returns a string in UTF8 format.
  740. UniqueSECItem decodeItem(CERT_DecodeAVAValue(&ava->value));
  741. if (!decodeItem) {
  742. return NS_ERROR_FAILURE;
  743. }
  744. // We know we can fit buffer of this length. CERT_RFC1485_EscapeAndQuote
  745. // will fail if we provide smaller buffer then the result can fit to.
  746. int escapedValueCapacity = decodeItem->len * 3 + 3;
  747. UniquePtr<char[]> escapedValue = MakeUnique<char[]>(escapedValueCapacity);
  748. SECStatus status = CERT_RFC1485_EscapeAndQuote(
  749. escapedValue.get(),
  750. escapedValueCapacity,
  751. (char*)decodeItem->data,
  752. decodeItem->len);
  753. if (SECSuccess != status) {
  754. return NS_ERROR_FAILURE;
  755. }
  756. avavalue = NS_ConvertUTF8toUTF16(escapedValue.get());
  757. params[0] = type.get();
  758. params[1] = avavalue.get();
  759. nssComponent->PIPBundleFormatStringFromName("AVATemplate",
  760. params, 2, temp);
  761. finalString += temp + NS_LITERAL_STRING("\n");
  762. }
  763. return NS_OK;
  764. }
  765. static nsresult
  766. ProcessName(CERTName *name, nsINSSComponent *nssComponent, char16_t **value)
  767. {
  768. CERTRDN** rdns;
  769. CERTRDN** rdn;
  770. nsString finalString;
  771. rdns = name->rdns;
  772. nsresult rv;
  773. CERTRDN **lastRdn;
  774. /* find last RDN */
  775. lastRdn = rdns;
  776. while (*lastRdn) lastRdn++;
  777. // The above whille loop will put us at the last member
  778. // of the array which is a nullptr pointer. So let's back
  779. // up one spot so that we have the last non-nullptr entry in
  780. // the array in preparation for traversing the
  781. // RDN's (Relative Distinguished Name) in reverse oder.
  782. lastRdn--;
  783. /*
  784. * Loop over name contents in _reverse_ RDN order appending to string
  785. * When building the Ascii string, NSS loops over these entries in
  786. * reverse order, so I will as well. The difference is that NSS
  787. * will always place them in a one line string separated by commas,
  788. * where I want each entry on a single line. I can't just use a comma
  789. * as my delimitter because it is a valid character to have in the
  790. * value portion of the AVA and could cause trouble when parsing.
  791. */
  792. for (rdn = lastRdn; rdn >= rdns; rdn--) {
  793. rv = ProcessRDN(*rdn, finalString, nssComponent);
  794. if (NS_FAILED(rv))
  795. return rv;
  796. }
  797. *value = ToNewUnicode(finalString);
  798. return NS_OK;
  799. }
  800. static nsresult
  801. ProcessIA5String(const SECItem& extData, /*in/out*/ nsAString& text)
  802. {
  803. ScopedAutoSECItem item;
  804. if (SEC_ASN1DecodeItem(nullptr, &item, SEC_ASN1_GET(SEC_IA5StringTemplate),
  805. &extData) != SECSuccess) {
  806. return NS_ERROR_FAILURE;
  807. }
  808. text.AppendASCII(BitwiseCast<char*, unsigned char*>(item.data),
  809. AssertedCast<uint32_t>(item.len));
  810. return NS_OK;
  811. }
  812. static nsresult
  813. AppendBMPtoUTF16(const UniquePLArenaPool& arena, unsigned char* data,
  814. unsigned int len, nsAString& text)
  815. {
  816. if (len % 2 != 0) {
  817. return NS_ERROR_FAILURE;
  818. }
  819. /* XXX instead of converting to and from UTF-8, it would
  820. be sufficient to just swap bytes, or do nothing */
  821. unsigned int utf8ValLen = len * 3 + 1;
  822. unsigned char* utf8Val = (unsigned char*)PORT_ArenaZAlloc(arena.get(),
  823. utf8ValLen);
  824. if (!PORT_UCS2_UTF8Conversion(false, data, len, utf8Val, utf8ValLen,
  825. &utf8ValLen)) {
  826. return NS_ERROR_FAILURE;
  827. }
  828. AppendUTF8toUTF16((char*)utf8Val, text);
  829. return NS_OK;
  830. }
  831. static nsresult
  832. ProcessBMPString(SECItem* extData, nsAString& text)
  833. {
  834. UniquePLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
  835. if (!arena) {
  836. return NS_ERROR_OUT_OF_MEMORY;
  837. }
  838. SECItem item;
  839. if (SEC_ASN1DecodeItem(arena.get(), &item, SEC_ASN1_GET(SEC_BMPStringTemplate),
  840. extData) != SECSuccess) {
  841. return NS_ERROR_FAILURE;
  842. }
  843. return AppendBMPtoUTF16(arena, item.data, item.len, text);
  844. }
  845. static nsresult
  846. ProcessGeneralName(const UniquePLArenaPool& arena, CERTGeneralName* current,
  847. nsAString& text, nsINSSComponent* nssComponent)
  848. {
  849. NS_ENSURE_ARG_POINTER(current);
  850. nsAutoString key;
  851. nsXPIDLString value;
  852. nsresult rv = NS_OK;
  853. switch (current->type) {
  854. case certOtherName: {
  855. SECOidTag oidTag = SECOID_FindOIDTag(&current->name.OthName.oid);
  856. if (oidTag == SEC_OID(MS_NT_PRINCIPAL_NAME)) {
  857. /* The type of this name is apparently nowhere explicitly
  858. documented. However, in the generated templates, it is always
  859. UTF-8. So try to decode this as UTF-8; if that fails, dump the
  860. raw data. */
  861. SECItem decoded;
  862. nssComponent->GetPIPNSSBundleString("CertDumpMSNTPrincipal", key);
  863. if (SEC_ASN1DecodeItem(arena.get(), &decoded,
  864. SEC_ASN1_GET(SEC_UTF8StringTemplate),
  865. &current->name.OthName.name) == SECSuccess) {
  866. AppendUTF8toUTF16(nsAutoCString((char*)decoded.data, decoded.len),
  867. value);
  868. } else {
  869. ProcessRawBytes(nssComponent, &current->name.OthName.name, value);
  870. }
  871. break;
  872. } else if (oidTag == SEC_OID(MS_NTDS_REPLICATION)) {
  873. /* This should be a 16-byte GUID */
  874. SECItem guid;
  875. nssComponent->GetPIPNSSBundleString("CertDumpMSDomainGUID", key);
  876. if (SEC_ASN1DecodeItem(arena.get(), &guid,
  877. SEC_ASN1_GET(SEC_OctetStringTemplate),
  878. &current->name.OthName.name) == SECSuccess
  879. && guid.len == 16) {
  880. char buf[40];
  881. unsigned char *d = guid.data;
  882. SprintfLiteral(buf,
  883. "{%.2x%.2x%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x%.2x%.2x%.2x%.2x}",
  884. d[3], d[2], d[1], d[0], d[5], d[4], d[7], d[6],
  885. d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
  886. value.AssignASCII(buf);
  887. } else {
  888. ProcessRawBytes(nssComponent, &current->name.OthName.name, value);
  889. }
  890. } else {
  891. rv = GetDefaultOIDFormat(&current->name.OthName.oid, nssComponent, key, ' ');
  892. if (NS_FAILED(rv)) {
  893. return rv;
  894. }
  895. ProcessRawBytes(nssComponent, &current->name.OthName.name, value);
  896. }
  897. break;
  898. }
  899. case certRFC822Name:
  900. nssComponent->GetPIPNSSBundleString("CertDumpRFC822Name", key);
  901. value.AssignASCII((char*)current->name.other.data, current->name.other.len);
  902. break;
  903. case certDNSName:
  904. nssComponent->GetPIPNSSBundleString("CertDumpDNSName", key);
  905. value.AssignASCII((char*)current->name.other.data, current->name.other.len);
  906. break;
  907. case certX400Address:
  908. nssComponent->GetPIPNSSBundleString("CertDumpX400Address", key);
  909. ProcessRawBytes(nssComponent, &current->name.other, value);
  910. break;
  911. case certDirectoryName:
  912. nssComponent->GetPIPNSSBundleString("CertDumpDirectoryName", key);
  913. rv = ProcessName(&current->name.directoryName, nssComponent,
  914. getter_Copies(value));
  915. if (NS_FAILED(rv)) {
  916. return rv;
  917. }
  918. break;
  919. case certEDIPartyName:
  920. nssComponent->GetPIPNSSBundleString("CertDumpEDIPartyName", key);
  921. ProcessRawBytes(nssComponent, &current->name.other, value);
  922. break;
  923. case certURI:
  924. nssComponent->GetPIPNSSBundleString("CertDumpURI", key);
  925. value.AssignASCII((char*)current->name.other.data, current->name.other.len);
  926. break;
  927. case certIPAddress:
  928. {
  929. PRStatus status = PR_FAILURE;
  930. // According to DNS.h, this includes space for the null-terminator
  931. char buf[net::kNetAddrMaxCStrBufSize] = {0};
  932. PRNetAddr addr;
  933. memset(&addr, 0, sizeof(addr));
  934. nssComponent->GetPIPNSSBundleString("CertDumpIPAddress", key);
  935. if (current->name.other.len == 4) {
  936. addr.inet.family = PR_AF_INET;
  937. memcpy(&addr.inet.ip, current->name.other.data, current->name.other.len);
  938. status = PR_NetAddrToString(&addr, buf, sizeof(buf));
  939. } else if (current->name.other.len == 16) {
  940. addr.ipv6.family = PR_AF_INET6;
  941. memcpy(&addr.ipv6.ip, current->name.other.data, current->name.other.len);
  942. status = PR_NetAddrToString(&addr, buf, sizeof(buf));
  943. }
  944. if (status == PR_SUCCESS) {
  945. value.AssignASCII(buf);
  946. } else {
  947. /* invalid IP address */
  948. ProcessRawBytes(nssComponent, &current->name.other, value);
  949. }
  950. break;
  951. }
  952. case certRegisterID:
  953. nssComponent->GetPIPNSSBundleString("CertDumpRegisterID", key);
  954. rv = GetDefaultOIDFormat(&current->name.other, nssComponent, value, '.');
  955. if (NS_FAILED(rv)) {
  956. return rv;
  957. }
  958. break;
  959. }
  960. text.Append(key);
  961. text.AppendLiteral(": ");
  962. text.Append(value);
  963. text.AppendLiteral(SEPARATOR);
  964. return rv;
  965. }
  966. static nsresult
  967. ProcessGeneralNames(const UniquePLArenaPool& arena, CERTGeneralName* nameList,
  968. nsAString& text, nsINSSComponent* nssComponent)
  969. {
  970. CERTGeneralName* current = nameList;
  971. nsresult rv;
  972. do {
  973. rv = ProcessGeneralName(arena, current, text, nssComponent);
  974. if (NS_FAILED(rv)) {
  975. break;
  976. }
  977. current = CERT_GetNextGeneralName(current);
  978. } while (current != nameList);
  979. return rv;
  980. }
  981. static nsresult
  982. ProcessAltName(SECItem* extData, nsAString& text, nsINSSComponent* nssComponent)
  983. {
  984. UniquePLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
  985. if (!arena) {
  986. return NS_ERROR_OUT_OF_MEMORY;
  987. }
  988. CERTGeneralName* nameList = CERT_DecodeAltNameExtension(arena.get(), extData);
  989. if (!nameList) {
  990. return NS_OK;
  991. }
  992. return ProcessGeneralNames(arena, nameList, text, nssComponent);
  993. }
  994. static nsresult
  995. ProcessSubjectKeyId(SECItem *extData,
  996. nsAString &text,
  997. nsINSSComponent *nssComponent)
  998. {
  999. SECItem decoded;
  1000. nsAutoString local;
  1001. UniquePLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
  1002. if (!arena) {
  1003. return NS_ERROR_OUT_OF_MEMORY;
  1004. }
  1005. if (SEC_QuickDERDecodeItem(arena.get(), &decoded,
  1006. SEC_ASN1_GET(SEC_OctetStringTemplate),
  1007. extData) != SECSuccess) {
  1008. return NS_ERROR_FAILURE;
  1009. }
  1010. nssComponent->GetPIPNSSBundleString("CertDumpKeyID", local);
  1011. text.Append(local);
  1012. text.AppendLiteral(": ");
  1013. ProcessRawBytes(nssComponent, &decoded, text);
  1014. return NS_OK;
  1015. }
  1016. static nsresult
  1017. ProcessAuthKeyId(SECItem *extData,
  1018. nsAString &text,
  1019. nsINSSComponent *nssComponent)
  1020. {
  1021. nsresult rv = NS_OK;
  1022. nsAutoString local;
  1023. UniquePLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
  1024. if (!arena) {
  1025. return NS_ERROR_OUT_OF_MEMORY;
  1026. }
  1027. CERTAuthKeyID* ret = CERT_DecodeAuthKeyID(arena.get(), extData);
  1028. if (!ret) {
  1029. return NS_ERROR_FAILURE;
  1030. }
  1031. if (ret->keyID.len > 0) {
  1032. nssComponent->GetPIPNSSBundleString("CertDumpKeyID", local);
  1033. text.Append(local);
  1034. text.AppendLiteral(": ");
  1035. ProcessRawBytes(nssComponent, &ret->keyID, text);
  1036. text.AppendLiteral(SEPARATOR);
  1037. }
  1038. if (ret->authCertIssuer) {
  1039. nssComponent->GetPIPNSSBundleString("CertDumpIssuer", local);
  1040. text.Append(local);
  1041. text.AppendLiteral(": ");
  1042. rv = ProcessGeneralNames(arena, ret->authCertIssuer, text, nssComponent);
  1043. if (NS_FAILED(rv)) {
  1044. return rv;
  1045. }
  1046. }
  1047. if (ret->authCertSerialNumber.len > 0) {
  1048. nssComponent->GetPIPNSSBundleString("CertDumpSerialNo", local);
  1049. text.Append(local);
  1050. text.AppendLiteral(": ");
  1051. ProcessRawBytes(nssComponent, &ret->authCertSerialNumber, text);
  1052. }
  1053. return rv;
  1054. }
  1055. static nsresult
  1056. ProcessUserNotice(SECItem* derNotice, nsAString& text,
  1057. nsINSSComponent* nssComponent)
  1058. {
  1059. UniquePLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
  1060. if (!arena) {
  1061. return NS_ERROR_OUT_OF_MEMORY;
  1062. }
  1063. UniqueCERTUserNotice notice(CERT_DecodeUserNotice(derNotice));
  1064. if (!notice) {
  1065. ProcessRawBytes(nssComponent, derNotice, text);
  1066. return NS_OK;
  1067. }
  1068. if (notice->noticeReference.organization.len != 0) {
  1069. switch (notice->noticeReference.organization.type) {
  1070. case siAsciiString:
  1071. case siVisibleString:
  1072. case siUTF8String:
  1073. text.Append(NS_ConvertUTF8toUTF16(
  1074. (const char *)notice->noticeReference.organization.data,
  1075. notice->noticeReference.organization.len));
  1076. break;
  1077. case siBMPString:
  1078. AppendBMPtoUTF16(arena, notice->noticeReference.organization.data,
  1079. notice->noticeReference.organization.len, text);
  1080. break;
  1081. default:
  1082. break;
  1083. }
  1084. text.AppendLiteral(" - ");
  1085. SECItem** itemList = notice->noticeReference.noticeNumbers;
  1086. while (*itemList) {
  1087. unsigned long number;
  1088. char buffer[60];
  1089. if (SEC_ASN1DecodeInteger(*itemList, &number) == SECSuccess) {
  1090. SprintfLiteral(buffer, "#%lu", number);
  1091. if (itemList != notice->noticeReference.noticeNumbers)
  1092. text.AppendLiteral(", ");
  1093. AppendASCIItoUTF16(buffer, text);
  1094. }
  1095. itemList++;
  1096. }
  1097. }
  1098. if (notice->displayText.len != 0) {
  1099. text.AppendLiteral(SEPARATOR);
  1100. text.AppendLiteral(" ");
  1101. switch (notice->displayText.type) {
  1102. case siAsciiString:
  1103. case siVisibleString:
  1104. case siUTF8String:
  1105. text.Append(NS_ConvertUTF8toUTF16((const char *)notice->displayText.data,
  1106. notice->displayText.len));
  1107. break;
  1108. case siBMPString:
  1109. AppendBMPtoUTF16(arena, notice->displayText.data, notice->displayText.len,
  1110. text);
  1111. break;
  1112. default:
  1113. break;
  1114. }
  1115. }
  1116. return NS_OK;
  1117. }
  1118. static nsresult
  1119. ProcessCertificatePolicies(SECItem *extData,
  1120. nsAString &text,
  1121. nsINSSComponent *nssComponent)
  1122. {
  1123. CERTPolicyInfo **policyInfos, *policyInfo;
  1124. CERTPolicyQualifier **policyQualifiers, *policyQualifier;
  1125. nsAutoString local;
  1126. nsresult rv = NS_OK;
  1127. UniqueCERTCertificatePolicies policies(
  1128. CERT_DecodeCertificatePoliciesExtension(extData));
  1129. if (!policies) {
  1130. return NS_ERROR_FAILURE;
  1131. }
  1132. policyInfos = policies->policyInfos;
  1133. while (*policyInfos) {
  1134. policyInfo = *policyInfos++;
  1135. switch (policyInfo->oid) {
  1136. case SEC_OID_VERISIGN_USER_NOTICES:
  1137. nssComponent->GetPIPNSSBundleString("CertDumpVerisignNotices", local);
  1138. text.Append(local);
  1139. break;
  1140. default:
  1141. GetDefaultOIDFormat(&policyInfo->policyID, nssComponent, local, '.');
  1142. text.Append(local);
  1143. }
  1144. if (policyInfo->policyQualifiers) {
  1145. /* Add all qualifiers on separate lines, indented */
  1146. policyQualifiers = policyInfo->policyQualifiers;
  1147. text.Append(':');
  1148. text.AppendLiteral(SEPARATOR);
  1149. while (*policyQualifiers) {
  1150. text.AppendLiteral(" ");
  1151. policyQualifier = *policyQualifiers++;
  1152. switch(policyQualifier->oid) {
  1153. case SEC_OID_PKIX_CPS_POINTER_QUALIFIER:
  1154. nssComponent->GetPIPNSSBundleString("CertDumpCPSPointer", local);
  1155. text.Append(local);
  1156. text.Append(':');
  1157. text.AppendLiteral(SEPARATOR);
  1158. text.AppendLiteral(" ");
  1159. /* The CPS pointer ought to be the cPSuri alternative
  1160. of the Qualifier choice. */
  1161. rv = ProcessIA5String(policyQualifier->qualifierValue, text);
  1162. if (NS_FAILED(rv)) {
  1163. return rv;
  1164. }
  1165. break;
  1166. case SEC_OID_PKIX_USER_NOTICE_QUALIFIER:
  1167. nssComponent->GetPIPNSSBundleString("CertDumpUserNotice", local);
  1168. text.Append(local);
  1169. text.AppendLiteral(": ");
  1170. rv = ProcessUserNotice(&policyQualifier->qualifierValue,
  1171. text, nssComponent);
  1172. break;
  1173. default:
  1174. GetDefaultOIDFormat(&policyQualifier->qualifierID, nssComponent, local, '.');
  1175. text.Append(local);
  1176. text.AppendLiteral(": ");
  1177. ProcessRawBytes(nssComponent, &policyQualifier->qualifierValue, text);
  1178. }
  1179. text.AppendLiteral(SEPARATOR);
  1180. } /* while policyQualifiers */
  1181. } /* if policyQualifiers */
  1182. text.AppendLiteral(SEPARATOR);
  1183. }
  1184. return rv;
  1185. }
  1186. static nsresult
  1187. ProcessCrlDistPoints(SECItem *extData,
  1188. nsAString &text,
  1189. nsINSSComponent *nssComponent)
  1190. {
  1191. nsresult rv = NS_OK;
  1192. nsAutoString local;
  1193. UniquePLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
  1194. if (!arena) {
  1195. return NS_ERROR_OUT_OF_MEMORY;
  1196. }
  1197. CERTCrlDistributionPoints* crldp =
  1198. CERT_DecodeCRLDistributionPoints(arena.get(), extData);
  1199. if (!crldp || !crldp->distPoints) {
  1200. return NS_ERROR_FAILURE;
  1201. }
  1202. for (CRLDistributionPoint** points = crldp->distPoints; *points; points++) {
  1203. CRLDistributionPoint* point = *points;
  1204. switch (point->distPointType) {
  1205. case generalName:
  1206. rv = ProcessGeneralName(arena, point->distPoint.fullName,
  1207. text, nssComponent);
  1208. if (NS_FAILED(rv)) {
  1209. return rv;
  1210. }
  1211. break;
  1212. case relativeDistinguishedName:
  1213. rv = ProcessRDN(&point->distPoint.relativeName,
  1214. text, nssComponent);
  1215. if (NS_FAILED(rv)) {
  1216. return rv;
  1217. }
  1218. break;
  1219. }
  1220. if (point->reasons.len) {
  1221. int reasons = point->reasons.data[0];
  1222. text.Append(' ');
  1223. bool comma = false;
  1224. if (reasons & RF_UNUSED) {
  1225. nssComponent->GetPIPNSSBundleString("CertDumpUnused", local);
  1226. text.Append(local);
  1227. comma = true;
  1228. }
  1229. if (reasons & RF_KEY_COMPROMISE) {
  1230. if (comma) text.AppendLiteral(", ");
  1231. nssComponent->GetPIPNSSBundleString("CertDumpKeyCompromise", local);
  1232. text.Append(local);
  1233. comma = true;
  1234. }
  1235. if (reasons & RF_CA_COMPROMISE) {
  1236. if (comma) text.AppendLiteral(", ");
  1237. nssComponent->GetPIPNSSBundleString("CertDumpCACompromise", local);
  1238. text.Append(local);
  1239. comma = true;
  1240. }
  1241. if (reasons & RF_AFFILIATION_CHANGED) {
  1242. if (comma) text.AppendLiteral(", ");
  1243. nssComponent->GetPIPNSSBundleString("CertDumpAffiliationChanged", local);
  1244. text.Append(local);
  1245. comma = true;
  1246. }
  1247. if (reasons & RF_SUPERSEDED) {
  1248. if (comma) text.AppendLiteral(", ");
  1249. nssComponent->GetPIPNSSBundleString("CertDumpSuperseded", local);
  1250. text.Append(local);
  1251. comma = true;
  1252. }
  1253. if (reasons & RF_CESSATION_OF_OPERATION) {
  1254. if (comma) text.AppendLiteral(", ");
  1255. nssComponent->GetPIPNSSBundleString("CertDumpCessation", local);
  1256. text.Append(local);
  1257. comma = true;
  1258. }
  1259. if (reasons & RF_CERTIFICATE_HOLD) {
  1260. if (comma) text.AppendLiteral(", ");
  1261. nssComponent->GetPIPNSSBundleString("CertDumpHold", local);
  1262. text.Append(local);
  1263. comma = true;
  1264. }
  1265. text.AppendLiteral(SEPARATOR);
  1266. }
  1267. if (point->crlIssuer) {
  1268. nssComponent->GetPIPNSSBundleString("CertDumpIssuer", local);
  1269. text.Append(local);
  1270. text.AppendLiteral(": ");
  1271. rv = ProcessGeneralNames(arena, point->crlIssuer,
  1272. text, nssComponent);
  1273. if (NS_FAILED(rv)) {
  1274. return rv;
  1275. }
  1276. }
  1277. }
  1278. return NS_OK;
  1279. }
  1280. static nsresult
  1281. ProcessAuthInfoAccess(SECItem *extData,
  1282. nsAString &text,
  1283. nsINSSComponent *nssComponent)
  1284. {
  1285. nsresult rv = NS_OK;
  1286. nsAutoString local;
  1287. UniquePLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
  1288. if (!arena) {
  1289. return NS_ERROR_OUT_OF_MEMORY;
  1290. }
  1291. CERTAuthInfoAccess** aia = CERT_DecodeAuthInfoAccessExtension(arena.get(),
  1292. extData);
  1293. if (!aia) {
  1294. return NS_OK;
  1295. }
  1296. while (*aia) {
  1297. CERTAuthInfoAccess* desc = *aia++;
  1298. switch (SECOID_FindOIDTag(&desc->method)) {
  1299. case SEC_OID_PKIX_OCSP:
  1300. nssComponent->GetPIPNSSBundleString("CertDumpOCSPResponder", local);
  1301. break;
  1302. case SEC_OID_PKIX_CA_ISSUERS:
  1303. nssComponent->GetPIPNSSBundleString("CertDumpCAIssuers", local);
  1304. break;
  1305. default:
  1306. rv = GetDefaultOIDFormat(&desc->method, nssComponent, local, '.');
  1307. if (NS_FAILED(rv)) {
  1308. return rv;
  1309. }
  1310. }
  1311. text.Append(local);
  1312. text.AppendLiteral(": ");
  1313. rv = ProcessGeneralName(arena, desc->location, text, nssComponent);
  1314. if (NS_FAILED(rv)) {
  1315. return rv;
  1316. }
  1317. }
  1318. return rv;
  1319. }
  1320. static nsresult
  1321. ProcessMSCAVersion(SECItem *extData,
  1322. nsAString &text,
  1323. nsINSSComponent *nssComponent)
  1324. {
  1325. MOZ_ASSERT(extData);
  1326. NS_ENSURE_ARG(extData);
  1327. ScopedAutoSECItem decoded;
  1328. if (SEC_ASN1DecodeItem(nullptr, &decoded, SEC_ASN1_GET(SEC_IntegerTemplate),
  1329. extData) != SECSuccess) {
  1330. /* This extension used to be an Integer when this code
  1331. was written, but apparently isn't anymore. Display
  1332. the raw bytes instead. */
  1333. return ProcessRawBytes(nssComponent, extData, text);
  1334. }
  1335. unsigned long version;
  1336. if (SEC_ASN1DecodeInteger(&decoded, &version) != SECSuccess) {
  1337. /* Value out of range, display raw bytes */
  1338. return ProcessRawBytes(nssComponent, extData, text);
  1339. }
  1340. /* Apparently, the encoding is <minor><major>, with 16 bits each */
  1341. char buf[50];
  1342. if (SprintfLiteral(buf, "%lu.%lu", version & 0xFFFF, version >> 16) <= 0) {
  1343. return NS_ERROR_FAILURE;
  1344. }
  1345. text.AppendASCII(buf);
  1346. return NS_OK;
  1347. }
  1348. static nsresult
  1349. ProcessExtensionData(SECOidTag oidTag, SECItem *extData,
  1350. nsAString &text,
  1351. nsINSSComponent *nssComponent)
  1352. {
  1353. nsresult rv;
  1354. switch (oidTag) {
  1355. case SEC_OID_X509_KEY_USAGE:
  1356. rv = ProcessKeyUsageExtension(extData, text, nssComponent);
  1357. break;
  1358. case SEC_OID_X509_BASIC_CONSTRAINTS:
  1359. rv = ProcessBasicConstraints(extData, text, nssComponent);
  1360. break;
  1361. case SEC_OID_X509_EXT_KEY_USAGE:
  1362. rv = ProcessExtKeyUsage(extData, text, nssComponent);
  1363. break;
  1364. case SEC_OID_X509_ISSUER_ALT_NAME:
  1365. case SEC_OID_X509_SUBJECT_ALT_NAME:
  1366. rv = ProcessAltName(extData, text, nssComponent);
  1367. break;
  1368. case SEC_OID_X509_SUBJECT_KEY_ID:
  1369. rv = ProcessSubjectKeyId(extData, text, nssComponent);
  1370. break;
  1371. case SEC_OID_X509_AUTH_KEY_ID:
  1372. rv = ProcessAuthKeyId(extData, text, nssComponent);
  1373. break;
  1374. case SEC_OID_X509_CERTIFICATE_POLICIES:
  1375. rv = ProcessCertificatePolicies(extData, text, nssComponent);
  1376. break;
  1377. case SEC_OID_X509_CRL_DIST_POINTS:
  1378. rv = ProcessCrlDistPoints(extData, text, nssComponent);
  1379. break;
  1380. case SEC_OID_X509_AUTH_INFO_ACCESS:
  1381. rv = ProcessAuthInfoAccess(extData, text, nssComponent);
  1382. break;
  1383. default:
  1384. if (oidTag == SEC_OID(MS_CERT_EXT_CERTTYPE)) {
  1385. rv = ProcessBMPString(extData, text);
  1386. break;
  1387. }
  1388. if (oidTag == SEC_OID(MS_CERTSERV_CA_VERSION)) {
  1389. rv = ProcessMSCAVersion(extData, text, nssComponent);
  1390. break;
  1391. }
  1392. rv = ProcessRawBytes(nssComponent, extData, text);
  1393. break;
  1394. }
  1395. return rv;
  1396. }
  1397. static nsresult
  1398. ProcessSingleExtension(CERTCertExtension *extension,
  1399. nsINSSComponent *nssComponent,
  1400. nsIASN1PrintableItem **retExtension)
  1401. {
  1402. nsAutoString text, extvalue;
  1403. GetOIDText(&extension->id, nssComponent, text);
  1404. nsCOMPtr<nsIASN1PrintableItem>extensionItem = new nsNSSASN1PrintableItem();
  1405. extensionItem->SetDisplayName(text);
  1406. SECOidTag oidTag = SECOID_FindOIDTag(&extension->id);
  1407. text.Truncate();
  1408. if (extension->critical.data) {
  1409. if (extension->critical.data[0]) {
  1410. nssComponent->GetPIPNSSBundleString("CertDumpCritical", text);
  1411. } else {
  1412. nssComponent->GetPIPNSSBundleString("CertDumpNonCritical", text);
  1413. }
  1414. } else {
  1415. nssComponent->GetPIPNSSBundleString("CertDumpNonCritical", text);
  1416. }
  1417. text.AppendLiteral(SEPARATOR);
  1418. nsresult rv = ProcessExtensionData(oidTag, &extension->value, extvalue,
  1419. nssComponent);
  1420. if (NS_FAILED(rv)) {
  1421. extvalue.Truncate();
  1422. rv = ProcessRawBytes(nssComponent, &extension->value, extvalue, false);
  1423. }
  1424. text.Append(extvalue);
  1425. extensionItem->SetDisplayValue(text);
  1426. extensionItem.forget(retExtension);
  1427. return NS_OK;
  1428. }
  1429. static nsresult
  1430. ProcessSECAlgorithmID(SECAlgorithmID *algID,
  1431. nsINSSComponent *nssComponent,
  1432. nsIASN1Sequence **retSequence)
  1433. {
  1434. SECOidTag algOIDTag = SECOID_FindOIDTag(&algID->algorithm);
  1435. SECItem paramsOID = { siBuffer, nullptr, 0 };
  1436. nsCOMPtr<nsIASN1Sequence> sequence = new nsNSSASN1Sequence();
  1437. *retSequence = nullptr;
  1438. nsString text;
  1439. GetOIDText(&algID->algorithm, nssComponent, text);
  1440. if (!algID->parameters.len || algID->parameters.data[0] == nsIASN1Object::ASN1_NULL) {
  1441. sequence->SetDisplayValue(text);
  1442. sequence->SetIsValidContainer(false);
  1443. } else {
  1444. nsCOMPtr<nsIASN1PrintableItem> printableItem = new nsNSSASN1PrintableItem();
  1445. printableItem->SetDisplayValue(text);
  1446. nsCOMPtr<nsIMutableArray> asn1Objects;
  1447. sequence->GetASN1Objects(getter_AddRefs(asn1Objects));
  1448. asn1Objects->AppendElement(printableItem, false);
  1449. nssComponent->GetPIPNSSBundleString("CertDumpAlgID", text);
  1450. printableItem->SetDisplayName(text);
  1451. printableItem = new nsNSSASN1PrintableItem();
  1452. asn1Objects->AppendElement(printableItem, false);
  1453. nssComponent->GetPIPNSSBundleString("CertDumpParams", text);
  1454. printableItem->SetDisplayName(text);
  1455. if ((algOIDTag == SEC_OID_ANSIX962_EC_PUBLIC_KEY) &&
  1456. (algID->parameters.len > 2) &&
  1457. (algID->parameters.data[0] == nsIASN1Object::ASN1_OBJECT_ID)) {
  1458. paramsOID.len = algID->parameters.len - 2;
  1459. paramsOID.data = algID->parameters.data + 2;
  1460. GetOIDText(&paramsOID, nssComponent, text);
  1461. } else {
  1462. ProcessRawBytes(nssComponent, &algID->parameters,text);
  1463. }
  1464. printableItem->SetDisplayValue(text);
  1465. }
  1466. sequence.forget(retSequence);
  1467. return NS_OK;
  1468. }
  1469. static nsresult
  1470. ProcessTime(PRTime dispTime, const char16_t* displayName,
  1471. nsIASN1Sequence* parentSequence)
  1472. {
  1473. nsCOMPtr<nsIDateTimeFormat> dateFormatter = nsIDateTimeFormat::Create();
  1474. if (!dateFormatter) {
  1475. return NS_ERROR_FAILURE;
  1476. }
  1477. nsString text;
  1478. nsString tempString;
  1479. PRExplodedTime explodedTime;
  1480. PR_ExplodeTime(dispTime, PR_LocalTimeParameters, &explodedTime);
  1481. dateFormatter->FormatPRExplodedTime(nullptr, kDateFormatLong,
  1482. kTimeFormatSeconds, &explodedTime,
  1483. tempString);
  1484. text.Append(tempString);
  1485. text.AppendLiteral("\n(");
  1486. PRExplodedTime explodedTimeGMT;
  1487. PR_ExplodeTime(dispTime, PR_GMTParameters, &explodedTimeGMT);
  1488. dateFormatter->FormatPRExplodedTime(nullptr, kDateFormatLong,
  1489. kTimeFormatSeconds, &explodedTimeGMT,
  1490. tempString);
  1491. text.Append(tempString);
  1492. text.AppendLiteral(" GMT)");
  1493. nsCOMPtr<nsIASN1PrintableItem> printableItem = new nsNSSASN1PrintableItem();
  1494. printableItem->SetDisplayValue(text);
  1495. printableItem->SetDisplayName(nsDependentString(displayName));
  1496. nsCOMPtr<nsIMutableArray> asn1Objects;
  1497. parentSequence->GetASN1Objects(getter_AddRefs(asn1Objects));
  1498. asn1Objects->AppendElement(printableItem, false);
  1499. return NS_OK;
  1500. }
  1501. static nsresult
  1502. ProcessSubjectPublicKeyInfo(CERTSubjectPublicKeyInfo *spki,
  1503. nsIASN1Sequence *parentSequence,
  1504. nsINSSComponent *nssComponent)
  1505. {
  1506. nsCOMPtr<nsIASN1Sequence> spkiSequence = new nsNSSASN1Sequence();
  1507. nsString text;
  1508. nssComponent->GetPIPNSSBundleString("CertDumpSPKI", text);
  1509. spkiSequence->SetDisplayName(text);
  1510. nssComponent->GetPIPNSSBundleString("CertDumpSPKIAlg", text);
  1511. nsCOMPtr<nsIASN1Sequence> sequenceItem;
  1512. nsresult rv = ProcessSECAlgorithmID(&spki->algorithm, nssComponent,
  1513. getter_AddRefs(sequenceItem));
  1514. if (NS_FAILED(rv))
  1515. return rv;
  1516. sequenceItem->SetDisplayName(text);
  1517. nsCOMPtr<nsIMutableArray> asn1Objects;
  1518. spkiSequence->GetASN1Objects(getter_AddRefs(asn1Objects));
  1519. asn1Objects->AppendElement(sequenceItem, false);
  1520. nsCOMPtr<nsIASN1PrintableItem> printableItem = new nsNSSASN1PrintableItem();
  1521. text.Truncate();
  1522. UniqueSECKEYPublicKey key(SECKEY_ExtractPublicKey(spki));
  1523. bool displayed = false;
  1524. if (key) {
  1525. switch (key->keyType) {
  1526. case rsaKey: {
  1527. displayed = true;
  1528. nsAutoString length1, length2, data1, data2;
  1529. length1.AppendInt(key->u.rsa.modulus.len * 8);
  1530. length2.AppendInt(key->u.rsa.publicExponent.len * 8);
  1531. ProcessRawBytes(nssComponent, &key->u.rsa.modulus, data1,
  1532. false);
  1533. ProcessRawBytes(nssComponent, &key->u.rsa.publicExponent, data2,
  1534. false);
  1535. const char16_t *params[4] = {length1.get(), data1.get(),
  1536. length2.get(), data2.get()};
  1537. nssComponent->PIPBundleFormatStringFromName("CertDumpRSATemplate",
  1538. params, 4, text);
  1539. break;
  1540. }
  1541. case ecKey: {
  1542. displayed = true;
  1543. SECKEYECPublicKey &ecpk = key->u.ec;
  1544. int fieldSizeLenAsBits =
  1545. SECKEY_ECParamsToKeySize(&ecpk.DEREncodedParams);
  1546. int basePointOrderLenAsBits =
  1547. SECKEY_ECParamsToBasePointOrderLen(&ecpk.DEREncodedParams);
  1548. nsAutoString s_fsl, s_bpol, s_pv;
  1549. s_fsl.AppendInt(fieldSizeLenAsBits);
  1550. s_bpol.AppendInt(basePointOrderLenAsBits);
  1551. if (ecpk.publicValue.len > 4) {
  1552. ProcessRawBytes(nssComponent, &ecpk.publicValue, s_pv, false);
  1553. } else {
  1554. int i_pv = DER_GetInteger(&ecpk.publicValue);
  1555. s_pv.AppendInt(i_pv);
  1556. }
  1557. const char16_t *params[] = {s_fsl.get(), s_bpol.get(), s_pv.get()};
  1558. nssComponent->PIPBundleFormatStringFromName("CertDumpECTemplate",
  1559. params, 3, text);
  1560. break;
  1561. }
  1562. default:
  1563. /* Algorithm unknown, or too rarely used to bother displaying it */
  1564. break;
  1565. }
  1566. }
  1567. if (!displayed) {
  1568. // Algorithm unknown, display raw bytes
  1569. // The subjectPublicKey field is encoded as a bit string.
  1570. // ProcessRawBytes expects the length to be in bytes, so
  1571. // let's convert the lenght into a temporary SECItem.
  1572. SECItem data;
  1573. data.data = spki->subjectPublicKey.data;
  1574. data.len = spki->subjectPublicKey.len / 8;
  1575. ProcessRawBytes(nssComponent, &data, text);
  1576. }
  1577. printableItem->SetDisplayValue(text);
  1578. nssComponent->GetPIPNSSBundleString("CertDumpSubjPubKey", text);
  1579. printableItem->SetDisplayName(text);
  1580. asn1Objects->AppendElement(printableItem, false);
  1581. parentSequence->GetASN1Objects(getter_AddRefs(asn1Objects));
  1582. asn1Objects->AppendElement(spkiSequence, false);
  1583. return NS_OK;
  1584. }
  1585. static nsresult
  1586. ProcessExtensions(CERTCertExtension **extensions,
  1587. nsIASN1Sequence *parentSequence,
  1588. nsINSSComponent *nssComponent)
  1589. {
  1590. nsCOMPtr<nsIASN1Sequence> extensionSequence = new nsNSSASN1Sequence;
  1591. nsString text;
  1592. nssComponent->GetPIPNSSBundleString("CertDumpExtensions", text);
  1593. extensionSequence->SetDisplayName(text);
  1594. int32_t i;
  1595. nsresult rv;
  1596. nsCOMPtr<nsIASN1PrintableItem> newExtension;
  1597. nsCOMPtr<nsIMutableArray> asn1Objects;
  1598. extensionSequence->GetASN1Objects(getter_AddRefs(asn1Objects));
  1599. for (i=0; extensions[i] != nullptr; i++) {
  1600. rv = ProcessSingleExtension(extensions[i],
  1601. nssComponent,
  1602. getter_AddRefs(newExtension));
  1603. if (NS_FAILED(rv))
  1604. return rv;
  1605. asn1Objects->AppendElement(newExtension, false);
  1606. }
  1607. parentSequence->GetASN1Objects(getter_AddRefs(asn1Objects));
  1608. asn1Objects->AppendElement(extensionSequence, false);
  1609. return NS_OK;
  1610. }
  1611. static bool registered;
  1612. static SECStatus RegisterDynamicOids()
  1613. {
  1614. unsigned int i;
  1615. SECStatus rv = SECSuccess;
  1616. if (registered)
  1617. return rv;
  1618. for (i = 0; i < numOids; i++) {
  1619. SECOidTag tag = SECOID_AddEntry(&more_oids[i]);
  1620. if (tag == SEC_OID_UNKNOWN) {
  1621. rv = SECFailure;
  1622. continue;
  1623. }
  1624. more_oids[i].offset = tag;
  1625. }
  1626. registered = true;
  1627. return rv;
  1628. }
  1629. nsresult
  1630. nsNSSCertificate::CreateTBSCertificateASN1Struct(nsIASN1Sequence **retSequence,
  1631. nsINSSComponent *nssComponent)
  1632. {
  1633. MOZ_ASSERT(nssComponent);
  1634. NS_ENSURE_ARG(nssComponent);
  1635. nsNSSShutDownPreventionLock locker;
  1636. if (isAlreadyShutDown())
  1637. return NS_ERROR_NOT_AVAILABLE;
  1638. if (RegisterDynamicOids() != SECSuccess)
  1639. return NS_ERROR_FAILURE;
  1640. //
  1641. // TBSCertificate ::= SEQUENCE {
  1642. // version [0] EXPLICIT Version DEFAULT v1,
  1643. // serialNumber CertificateSerialNumber,
  1644. // signature AlgorithmIdentifier,
  1645. // issuer Name,
  1646. // validity Validity,
  1647. // subject Name,
  1648. // subjectPublicKeyInfo SubjectPublicKeyInfo,
  1649. // issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
  1650. // -- If present, version shall be v2 or v3
  1651. // subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
  1652. // -- If present, version shall be v2 or v3
  1653. // extensions [3] EXPLICIT Extensions OPTIONAL
  1654. // -- If present, version shall be v3
  1655. // }
  1656. //
  1657. // This is the ASN1 structure we should be dealing with at this point.
  1658. // The code in this method will assert this is the structure we're dealing
  1659. // and then add more user friendly text for that field.
  1660. nsCOMPtr<nsIASN1Sequence> sequence = new nsNSSASN1Sequence();
  1661. nsString text;
  1662. nssComponent->GetPIPNSSBundleString("CertDumpCertificate", text);
  1663. sequence->SetDisplayName(text);
  1664. nsCOMPtr<nsIASN1PrintableItem> printableItem;
  1665. nsCOMPtr<nsIMutableArray> asn1Objects;
  1666. sequence->GetASN1Objects(getter_AddRefs(asn1Objects));
  1667. nsresult rv = ProcessVersion(&mCert->version, nssComponent,
  1668. getter_AddRefs(printableItem));
  1669. if (NS_FAILED(rv))
  1670. return rv;
  1671. asn1Objects->AppendElement(printableItem, false);
  1672. rv = ProcessSerialNumberDER(mCert->serialNumber, WrapNotNull(nssComponent),
  1673. printableItem);
  1674. if (NS_FAILED(rv))
  1675. return rv;
  1676. asn1Objects->AppendElement(printableItem, false);
  1677. nsCOMPtr<nsIASN1Sequence> algID;
  1678. rv = ProcessSECAlgorithmID(&mCert->signature,
  1679. nssComponent, getter_AddRefs(algID));
  1680. if (NS_FAILED(rv))
  1681. return rv;
  1682. nssComponent->GetPIPNSSBundleString("CertDumpSigAlg", text);
  1683. algID->SetDisplayName(text);
  1684. asn1Objects->AppendElement(algID, false);
  1685. nsXPIDLString value;
  1686. ProcessName(&mCert->issuer, nssComponent, getter_Copies(value));
  1687. printableItem = new nsNSSASN1PrintableItem();
  1688. printableItem->SetDisplayValue(value);
  1689. nssComponent->GetPIPNSSBundleString("CertDumpIssuer", text);
  1690. printableItem->SetDisplayName(text);
  1691. asn1Objects->AppendElement(printableItem, false);
  1692. nsCOMPtr<nsIASN1Sequence> validitySequence = new nsNSSASN1Sequence();
  1693. nssComponent->GetPIPNSSBundleString("CertDumpValidity", text);
  1694. validitySequence->SetDisplayName(text);
  1695. asn1Objects->AppendElement(validitySequence, false);
  1696. nssComponent->GetPIPNSSBundleString("CertDumpNotBefore", text);
  1697. nsCOMPtr<nsIX509CertValidity> validityData;
  1698. GetValidity(getter_AddRefs(validityData));
  1699. PRTime notBefore, notAfter;
  1700. validityData->GetNotBefore(&notBefore);
  1701. validityData->GetNotAfter(&notAfter);
  1702. validityData = nullptr;
  1703. rv = ProcessTime(notBefore, text.get(), validitySequence);
  1704. if (NS_FAILED(rv))
  1705. return rv;
  1706. nssComponent->GetPIPNSSBundleString("CertDumpNotAfter", text);
  1707. rv = ProcessTime(notAfter, text.get(), validitySequence);
  1708. if (NS_FAILED(rv))
  1709. return rv;
  1710. nssComponent->GetPIPNSSBundleString("CertDumpSubject", text);
  1711. printableItem = new nsNSSASN1PrintableItem();
  1712. printableItem->SetDisplayName(text);
  1713. ProcessName(&mCert->subject, nssComponent,getter_Copies(value));
  1714. printableItem->SetDisplayValue(value);
  1715. asn1Objects->AppendElement(printableItem, false);
  1716. rv = ProcessSubjectPublicKeyInfo(&mCert->subjectPublicKeyInfo, sequence,
  1717. nssComponent);
  1718. if (NS_FAILED(rv))
  1719. return rv;
  1720. SECItem data;
  1721. // Is there an issuerUniqueID?
  1722. if (mCert->issuerID.data) {
  1723. // The issuerID is encoded as a bit string.
  1724. // The function ProcessRawBytes expects the
  1725. // length to be in bytes, so let's convert the
  1726. // length in a temporary SECItem
  1727. data.data = mCert->issuerID.data;
  1728. data.len = (mCert->issuerID.len + 7) / 8;
  1729. ProcessRawBytes(nssComponent, &data, text);
  1730. printableItem = new nsNSSASN1PrintableItem();
  1731. printableItem->SetDisplayValue(text);
  1732. nssComponent->GetPIPNSSBundleString("CertDumpIssuerUniqueID", text);
  1733. printableItem->SetDisplayName(text);
  1734. asn1Objects->AppendElement(printableItem, false);
  1735. }
  1736. if (mCert->subjectID.data) {
  1737. // The subjectID is encoded as a bit string.
  1738. // The function ProcessRawBytes expects the
  1739. // length to be in bytes, so let's convert the
  1740. // length in a temporary SECItem
  1741. data.data = mCert->subjectID.data;
  1742. data.len = (mCert->subjectID.len + 7) / 8;
  1743. ProcessRawBytes(nssComponent, &data, text);
  1744. printableItem = new nsNSSASN1PrintableItem();
  1745. printableItem->SetDisplayValue(text);
  1746. nssComponent->GetPIPNSSBundleString("CertDumpSubjectUniqueID", text);
  1747. printableItem->SetDisplayName(text);
  1748. asn1Objects->AppendElement(printableItem, false);
  1749. }
  1750. if (mCert->extensions) {
  1751. rv = ProcessExtensions(mCert->extensions, sequence, nssComponent);
  1752. if (NS_FAILED(rv))
  1753. return rv;
  1754. }
  1755. sequence.forget(retSequence);
  1756. return NS_OK;
  1757. }
  1758. nsresult
  1759. nsNSSCertificate::CreateASN1Struct(nsIASN1Object** aRetVal)
  1760. {
  1761. static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
  1762. nsNSSShutDownPreventionLock locker;
  1763. if (isAlreadyShutDown())
  1764. return NS_ERROR_NOT_AVAILABLE;
  1765. nsCOMPtr<nsIASN1Sequence> sequence = new nsNSSASN1Sequence();
  1766. nsCOMPtr<nsIMutableArray> asn1Objects;
  1767. sequence->GetASN1Objects(getter_AddRefs(asn1Objects));
  1768. nsAutoString title;
  1769. nsresult rv = GetWindowTitle(title);
  1770. if (NS_FAILED(rv)) {
  1771. return rv;
  1772. }
  1773. sequence->SetDisplayName(title);
  1774. sequence.forget(aRetVal);
  1775. // This sequence will be contain the tbsCertificate, signatureAlgorithm,
  1776. // and signatureValue.
  1777. nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
  1778. if (NS_FAILED(rv))
  1779. return rv;
  1780. rv = CreateTBSCertificateASN1Struct(getter_AddRefs(sequence),
  1781. nssComponent);
  1782. if (NS_FAILED(rv))
  1783. return rv;
  1784. asn1Objects->AppendElement(sequence, false);
  1785. nsCOMPtr<nsIASN1Sequence> algID;
  1786. rv = ProcessSECAlgorithmID(&mCert->signatureWrap.signatureAlgorithm,
  1787. nssComponent, getter_AddRefs(algID));
  1788. if (NS_FAILED(rv))
  1789. return rv;
  1790. nsString text;
  1791. nssComponent->GetPIPNSSBundleString("CertDumpSigAlg", text);
  1792. algID->SetDisplayName(text);
  1793. asn1Objects->AppendElement(algID, false);
  1794. nsCOMPtr<nsIASN1PrintableItem>printableItem = new nsNSSASN1PrintableItem();
  1795. nssComponent->GetPIPNSSBundleString("CertDumpCertSig", text);
  1796. printableItem->SetDisplayName(text);
  1797. // The signatureWrap is encoded as a bit string.
  1798. // The function ProcessRawBytes expects the
  1799. // length to be in bytes, so let's convert the
  1800. // length in a temporary SECItem
  1801. SECItem temp;
  1802. temp.data = mCert->signatureWrap.signature.data;
  1803. temp.len = mCert->signatureWrap.signature.len / 8;
  1804. text.Truncate();
  1805. ProcessRawBytes(nssComponent, &temp,text);
  1806. printableItem->SetDisplayValue(text);
  1807. asn1Objects->AppendElement(printableItem, false);
  1808. return NS_OK;
  1809. }
  1810. uint32_t
  1811. getCertType(CERTCertificate *cert)
  1812. {
  1813. nsNSSCertTrust trust(cert->trust);
  1814. if (cert->nickname && trust.HasAnyUser())
  1815. return nsIX509Cert::USER_CERT;
  1816. if (trust.HasAnyCA())
  1817. return nsIX509Cert::CA_CERT;
  1818. if (trust.HasPeer(true, false, false))
  1819. return nsIX509Cert::SERVER_CERT;
  1820. if (trust.HasPeer(false, true, false) && cert->emailAddr)
  1821. return nsIX509Cert::EMAIL_CERT;
  1822. if (CERT_IsCACert(cert, nullptr))
  1823. return nsIX509Cert::CA_CERT;
  1824. if (cert->emailAddr)
  1825. return nsIX509Cert::EMAIL_CERT;
  1826. return nsIX509Cert::UNKNOWN_CERT;
  1827. }
  1828. nsresult
  1829. GetCertFingerprintByOidTag(CERTCertificate* nsscert,
  1830. SECOidTag aOidTag,
  1831. nsCString &fp)
  1832. {
  1833. Digest digest;
  1834. nsresult rv = digest.DigestBuf(aOidTag, nsscert->derCert.data,
  1835. nsscert->derCert.len);
  1836. NS_ENSURE_SUCCESS(rv, rv);
  1837. UniquePORTString tmpstr(CERT_Hexify(const_cast<SECItem*>(&digest.get()), 1));
  1838. NS_ENSURE_TRUE(tmpstr, NS_ERROR_OUT_OF_MEMORY);
  1839. fp.Assign(tmpstr.get());
  1840. return NS_OK;
  1841. }