- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / third_party / mozilla_security_manager / nsNSSCertHelper.cpp
1 /* ***** BEGIN LICENSE BLOCK *****
2  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3  *
4  * The contents of this file are subject to the Mozilla Public License Version
5  * 1.1 (the "License"); you may not use this file except in compliance with
6  * the License. You may obtain a copy of the License at
7  * http://www.mozilla.org/MPL/
8  *
9  * Software distributed under the License is distributed on an "AS IS" basis,
10  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11  * for the specific language governing rights and limitations under the
12  * License.
13  *
14  * The Original Code is the Netscape security libraries.
15  *
16  * The Initial Developer of the Original Code is
17  * Netscape Communications Corporation.
18  * Portions created by the Initial Developer are Copyright (C) 2000
19  * the Initial Developer. All Rights Reserved.
20  *
21  * Contributor(s):
22  *   Ian McGreer <mcgreer@netscape.com>
23  *   Javier Delgadillo <javi@netscape.com>
24  *   John Gardiner Myers <jgmyers@speakeasy.net>
25  *   Martin v. Loewis <martin@v.loewis.de>
26  *
27  * Alternatively, the contents of this file may be used under the terms of
28  * either the GNU General Public License Version 2 or later (the "GPL"), or
29  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30  * in which case the provisions of the GPL or the LGPL are applicable instead
31  * of those above. If you wish to allow use of your version of this file only
32  * under the terms of either the GPL or the LGPL, and not to allow others to
33  * use your version of this file under the terms of the MPL, indicate your
34  * decision by deleting the provisions above and replace them with the notice
35  * and other provisions required by the GPL or the LGPL. If you do not delete
36  * the provisions above, a recipient may use your version of this file under
37  * the terms of any one of the MPL, the GPL or the LGPL.
38  *
39  * ***** END LICENSE BLOCK ***** */
40
41 #include "chrome/third_party/mozilla_security_manager/nsNSSCertHelper.h"
42
43 #include <certdb.h>
44 #include <keyhi.h>
45 #include <prprf.h>
46 #include <unicode/uidna.h>
47
48 #include "base/i18n/number_formatting.h"
49 #include "base/strings/string_number_conversions.h"
50 #include "base/strings/stringprintf.h"
51 #include "base/strings/utf_string_conversions.h"
52 #include "chrome/common/net/x509_certificate_model.h"
53 #include "crypto/scoped_nss_types.h"
54 #include "grit/generated_resources.h"
55 #include "net/base/ip_endpoint.h"
56 #include "net/base/net_util.h"
57 #include "ui/base/l10n/l10n_util.h"
58
59 #if !defined(CERTDB_TERMINAL_RECORD)
60 /* NSS 3.13 renames CERTDB_VALID_PEER to CERTDB_TERMINAL_RECORD
61  * and marks CERTDB_VALID_PEER as deprecated.
62  * If we're using an older version, rename it ourselves.
63  */
64 #define CERTDB_TERMINAL_RECORD CERTDB_VALID_PEER
65 #endif
66
67 namespace {
68
69 std::string BMPtoUTF8(PRArenaPool* arena, unsigned char* data,
70                       unsigned int len) {
71   if (len % 2 != 0)
72     return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR);
73
74   unsigned int utf8_val_len = len * 3 + 1;
75   std::vector<unsigned char> utf8_val(utf8_val_len);
76   if (!PORT_UCS2_UTF8Conversion(PR_FALSE, data, len,
77                                 &utf8_val.front(), utf8_val_len, &utf8_val_len))
78     return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR);
79   return std::string(reinterpret_cast<char*>(&utf8_val.front()), utf8_val_len);
80 }
81
82 SECOidTag RegisterDynamicOid(const char* oid_string) {
83   SECOidTag rv = SEC_OID_UNKNOWN;
84   unsigned char buffer[1024];
85   SECOidData od;
86   od.oid.type = siDEROID;
87   od.oid.data = buffer;
88   od.oid.len = sizeof(buffer);
89
90   if (SEC_StringToOID(NULL, &od.oid, oid_string, 0) == SECSuccess) {
91     od.offset = SEC_OID_UNKNOWN;
92     od.mechanism = CKM_INVALID_MECHANISM;
93     od.supportedExtension = INVALID_CERT_EXTENSION;
94     od.desc = oid_string;
95
96     rv = SECOID_AddEntry(&od);
97   }
98   DCHECK_NE(rv, SEC_OID_UNKNOWN) << oid_string;
99   return rv;
100 }
101
102 // Format a SECItem as a space separated string, with 16 bytes on each line.
103 std::string ProcessRawBytes(SECItem* data) {
104   return x509_certificate_model::ProcessRawBytes(data->data, data->len);
105 }
106
107 }  // namespace
108
109 namespace mozilla_security_manager {
110
111 SECOidTag ms_cert_ext_certtype = SEC_OID_UNKNOWN;
112 SECOidTag ms_certsrv_ca_version = SEC_OID_UNKNOWN;
113 SECOidTag ms_nt_principal_name = SEC_OID_UNKNOWN;
114 SECOidTag ms_ntds_replication = SEC_OID_UNKNOWN;
115 SECOidTag eku_ms_individual_code_signing = SEC_OID_UNKNOWN;
116 SECOidTag eku_ms_commercial_code_signing = SEC_OID_UNKNOWN;
117 SECOidTag eku_ms_trust_list_signing = SEC_OID_UNKNOWN;
118 SECOidTag eku_ms_time_stamping = SEC_OID_UNKNOWN;
119 SECOidTag eku_ms_server_gated_crypto = SEC_OID_UNKNOWN;
120 SECOidTag eku_ms_encrypting_file_system = SEC_OID_UNKNOWN;
121 SECOidTag eku_ms_file_recovery = SEC_OID_UNKNOWN;
122 SECOidTag eku_ms_windows_hardware_driver_verification = SEC_OID_UNKNOWN;
123 SECOidTag eku_ms_qualified_subordination = SEC_OID_UNKNOWN;
124 SECOidTag eku_ms_key_recovery = SEC_OID_UNKNOWN;
125 SECOidTag eku_ms_document_signing = SEC_OID_UNKNOWN;
126 SECOidTag eku_ms_lifetime_signing = SEC_OID_UNKNOWN;
127 SECOidTag eku_ms_smart_card_logon = SEC_OID_UNKNOWN;
128 SECOidTag eku_ms_key_recovery_agent = SEC_OID_UNKNOWN;
129 SECOidTag eku_netscape_international_step_up = SEC_OID_UNKNOWN;
130 SECOidTag cert_attribute_business_category = SEC_OID_UNKNOWN;
131 SECOidTag cert_attribute_ev_incorporation_country = SEC_OID_UNKNOWN;
132
133 void RegisterDynamicOids() {
134   if (ms_cert_ext_certtype != SEC_OID_UNKNOWN)
135     return;
136
137   ms_cert_ext_certtype = RegisterDynamicOid("1.3.6.1.4.1.311.20.2");
138   ms_certsrv_ca_version = RegisterDynamicOid("1.3.6.1.4.1.311.21.1");
139   ms_nt_principal_name = RegisterDynamicOid("1.3.6.1.4.1.311.20.2.3");
140   ms_ntds_replication = RegisterDynamicOid("1.3.6.1.4.1.311.25.1");
141
142   eku_ms_individual_code_signing = RegisterDynamicOid("1.3.6.1.4.1.311.2.1.21");
143   eku_ms_commercial_code_signing = RegisterDynamicOid("1.3.6.1.4.1.311.2.1.22");
144   eku_ms_trust_list_signing = RegisterDynamicOid("1.3.6.1.4.1.311.10.3.1");
145   eku_ms_time_stamping = RegisterDynamicOid("1.3.6.1.4.1.311.10.3.2");
146   eku_ms_server_gated_crypto = RegisterDynamicOid("1.3.6.1.4.1.311.10.3.3");
147   eku_ms_encrypting_file_system = RegisterDynamicOid("1.3.6.1.4.1.311.10.3.4");
148   eku_ms_file_recovery = RegisterDynamicOid("1.3.6.1.4.1.311.10.3.4.1");
149   eku_ms_windows_hardware_driver_verification = RegisterDynamicOid(
150       "1.3.6.1.4.1.311.10.3.5");
151   eku_ms_qualified_subordination = RegisterDynamicOid(
152       "1.3.6.1.4.1.311.10.3.10");
153   eku_ms_key_recovery = RegisterDynamicOid("1.3.6.1.4.1.311.10.3.11");
154   eku_ms_document_signing = RegisterDynamicOid("1.3.6.1.4.1.311.10.3.12");
155   eku_ms_lifetime_signing = RegisterDynamicOid("1.3.6.1.4.1.311.10.3.13");
156   eku_ms_smart_card_logon = RegisterDynamicOid("1.3.6.1.4.1.311.20.2.2");
157   eku_ms_key_recovery_agent = RegisterDynamicOid("1.3.6.1.4.1.311.21.6");
158   eku_netscape_international_step_up = RegisterDynamicOid(
159       "2.16.840.1.113730.4.1");
160
161   // These two OIDs will be built-in as SEC_OID_BUSINESS_CATEGORY and
162   // SEC_OID_EV_INCORPORATION_COUNTRY starting in NSS 3.13.  Until then,
163   // we need to add them dynamically.
164   cert_attribute_business_category = RegisterDynamicOid("2.5.4.15");
165   cert_attribute_ev_incorporation_country = RegisterDynamicOid(
166       "1.3.6.1.4.1.311.60.2.1.3");
167 }
168
169 std::string DumpOidString(SECItem* oid) {
170   char* pr_string = CERT_GetOidString(oid);
171   if (pr_string) {
172     std::string rv = pr_string;
173     PR_smprintf_free(pr_string);
174     return rv;
175   }
176
177   return ProcessRawBytes(oid);
178 }
179
180 std::string GetOIDText(SECItem* oid) {
181   int string_id;
182   SECOidTag oid_tag = SECOID_FindOIDTag(oid);
183   switch (oid_tag) {
184     case SEC_OID_AVA_COMMON_NAME:
185       string_id = IDS_CERT_OID_AVA_COMMON_NAME;
186       break;
187     case SEC_OID_AVA_STATE_OR_PROVINCE:
188       string_id = IDS_CERT_OID_AVA_STATE_OR_PROVINCE;
189       break;
190     case SEC_OID_AVA_ORGANIZATION_NAME:
191       string_id = IDS_CERT_OID_AVA_ORGANIZATION_NAME;
192       break;
193     case SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME:
194       string_id = IDS_CERT_OID_AVA_ORGANIZATIONAL_UNIT_NAME;
195       break;
196     case SEC_OID_AVA_DN_QUALIFIER:
197       string_id = IDS_CERT_OID_AVA_DN_QUALIFIER;
198       break;
199     case SEC_OID_AVA_COUNTRY_NAME:
200       string_id = IDS_CERT_OID_AVA_COUNTRY_NAME;
201       break;
202     case SEC_OID_AVA_SERIAL_NUMBER:
203       string_id = IDS_CERT_OID_AVA_SERIAL_NUMBER;
204       break;
205     case SEC_OID_AVA_LOCALITY:
206       string_id = IDS_CERT_OID_AVA_LOCALITY;
207       break;
208     case SEC_OID_AVA_DC:
209       string_id = IDS_CERT_OID_AVA_DC;
210       break;
211     case SEC_OID_RFC1274_MAIL:
212       string_id = IDS_CERT_OID_RFC1274_MAIL;
213       break;
214     case SEC_OID_RFC1274_UID:
215       string_id = IDS_CERT_OID_RFC1274_UID;
216       break;
217     case SEC_OID_PKCS9_EMAIL_ADDRESS:
218       string_id = IDS_CERT_OID_PKCS9_EMAIL_ADDRESS;
219       break;
220     case SEC_OID_PKCS1_RSA_ENCRYPTION:
221       string_id = IDS_CERT_OID_PKCS1_RSA_ENCRYPTION;
222       break;
223     case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
224       string_id = IDS_CERT_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION;
225       break;
226     case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION:
227       string_id = IDS_CERT_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION;
228       break;
229     case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
230       string_id = IDS_CERT_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
231       break;
232     case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
233       string_id = IDS_CERT_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
234       break;
235     case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
236       string_id = IDS_CERT_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
237       break;
238     case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
239       string_id = IDS_CERT_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION;
240       break;
241     case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
242       string_id = IDS_CERT_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;
243       break;
244     case SEC_OID_NS_CERT_EXT_CERT_TYPE:
245       string_id = IDS_CERT_EXT_NS_CERT_TYPE;
246       break;
247     case SEC_OID_NS_CERT_EXT_BASE_URL:
248       string_id = IDS_CERT_EXT_NS_CERT_BASE_URL;
249       break;
250     case SEC_OID_NS_CERT_EXT_REVOCATION_URL:
251       string_id = IDS_CERT_EXT_NS_CERT_REVOCATION_URL;
252       break;
253     case SEC_OID_NS_CERT_EXT_CA_REVOCATION_URL:
254       string_id = IDS_CERT_EXT_NS_CA_REVOCATION_URL;
255       break;
256     case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_URL:
257       string_id = IDS_CERT_EXT_NS_CERT_RENEWAL_URL;
258       break;
259     case SEC_OID_NS_CERT_EXT_CA_POLICY_URL:
260       string_id = IDS_CERT_EXT_NS_CA_POLICY_URL;
261       break;
262     case SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME:
263       string_id = IDS_CERT_EXT_NS_SSL_SERVER_NAME;
264       break;
265     case SEC_OID_NS_CERT_EXT_COMMENT:
266       string_id = IDS_CERT_EXT_NS_COMMENT;
267       break;
268     case SEC_OID_NS_CERT_EXT_LOST_PASSWORD_URL:
269       string_id = IDS_CERT_EXT_NS_LOST_PASSWORD_URL;
270       break;
271     case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_TIME:
272       string_id = IDS_CERT_EXT_NS_CERT_RENEWAL_TIME;
273       break;
274     case SEC_OID_X509_SUBJECT_DIRECTORY_ATTR:
275       string_id = IDS_CERT_X509_SUBJECT_DIRECTORY_ATTR;
276       break;
277     case SEC_OID_X509_SUBJECT_KEY_ID:
278       string_id = IDS_CERT_X509_SUBJECT_KEYID;
279       break;
280     case SEC_OID_X509_KEY_USAGE:
281       string_id = IDS_CERT_X509_KEY_USAGE;
282       break;
283     case SEC_OID_X509_SUBJECT_ALT_NAME:
284       string_id = IDS_CERT_X509_SUBJECT_ALT_NAME;
285       break;
286     case SEC_OID_X509_ISSUER_ALT_NAME:
287       string_id = IDS_CERT_X509_ISSUER_ALT_NAME;
288       break;
289     case SEC_OID_X509_BASIC_CONSTRAINTS:
290       string_id = IDS_CERT_X509_BASIC_CONSTRAINTS;
291       break;
292     case SEC_OID_X509_NAME_CONSTRAINTS:
293       string_id = IDS_CERT_X509_NAME_CONSTRAINTS;
294       break;
295     case SEC_OID_X509_CRL_DIST_POINTS:
296       string_id = IDS_CERT_X509_CRL_DIST_POINTS;
297       break;
298     case SEC_OID_X509_CERTIFICATE_POLICIES:
299       string_id = IDS_CERT_X509_CERT_POLICIES;
300       break;
301     case SEC_OID_X509_POLICY_MAPPINGS:
302       string_id = IDS_CERT_X509_POLICY_MAPPINGS;
303       break;
304     case SEC_OID_X509_POLICY_CONSTRAINTS:
305       string_id = IDS_CERT_X509_POLICY_CONSTRAINTS;
306       break;
307     case SEC_OID_X509_AUTH_KEY_ID:
308       string_id = IDS_CERT_X509_AUTH_KEYID;
309       break;
310     case SEC_OID_X509_EXT_KEY_USAGE:
311       string_id = IDS_CERT_X509_EXT_KEY_USAGE;
312       break;
313     case SEC_OID_X509_AUTH_INFO_ACCESS:
314       string_id = IDS_CERT_X509_AUTH_INFO_ACCESS;
315       break;
316     case SEC_OID_EXT_KEY_USAGE_SERVER_AUTH:
317       string_id = IDS_CERT_EKU_TLS_WEB_SERVER_AUTHENTICATION;
318       break;
319     case SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH:
320       string_id = IDS_CERT_EKU_TLS_WEB_CLIENT_AUTHENTICATION;
321       break;
322     case SEC_OID_EXT_KEY_USAGE_CODE_SIGN:
323       string_id = IDS_CERT_EKU_CODE_SIGNING;
324       break;
325     case SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT:
326       string_id = IDS_CERT_EKU_EMAIL_PROTECTION;
327       break;
328     case SEC_OID_EXT_KEY_USAGE_TIME_STAMP:
329       string_id = IDS_CERT_EKU_TIME_STAMPING;
330       break;
331     case SEC_OID_OCSP_RESPONDER:
332       string_id = IDS_CERT_EKU_OCSP_SIGNING;
333       break;
334     case SEC_OID_PKIX_CPS_POINTER_QUALIFIER:
335       string_id = IDS_CERT_PKIX_CPS_POINTER_QUALIFIER;
336       break;
337     case SEC_OID_PKIX_USER_NOTICE_QUALIFIER:
338       string_id = IDS_CERT_PKIX_USER_NOTICE_QUALIFIER;
339       break;
340     case SEC_OID_UNKNOWN:
341       string_id = -1;
342       break;
343
344     // There are a billionty other OIDs we could add here.  I tried to get the
345     // important ones...
346     default:
347       if (oid_tag == ms_cert_ext_certtype)
348         string_id = IDS_CERT_EXT_MS_CERT_TYPE;
349       else if (oid_tag == ms_certsrv_ca_version)
350         string_id = IDS_CERT_EXT_MS_CA_VERSION;
351       else if (oid_tag == ms_nt_principal_name)
352         string_id = IDS_CERT_EXT_MS_NT_PRINCIPAL_NAME;
353       else if (oid_tag == ms_ntds_replication)
354         string_id = IDS_CERT_EXT_MS_NTDS_REPLICATION;
355       else if (oid_tag == eku_ms_individual_code_signing)
356         string_id = IDS_CERT_EKU_MS_INDIVIDUAL_CODE_SIGNING;
357       else if (oid_tag == eku_ms_commercial_code_signing)
358         string_id = IDS_CERT_EKU_MS_COMMERCIAL_CODE_SIGNING;
359       else if (oid_tag == eku_ms_trust_list_signing)
360         string_id = IDS_CERT_EKU_MS_TRUST_LIST_SIGNING;
361       else if (oid_tag == eku_ms_time_stamping)
362         string_id = IDS_CERT_EKU_MS_TIME_STAMPING;
363       else if (oid_tag == eku_ms_server_gated_crypto)
364         string_id = IDS_CERT_EKU_MS_SERVER_GATED_CRYPTO;
365       else if (oid_tag == eku_ms_encrypting_file_system)
366         string_id = IDS_CERT_EKU_MS_ENCRYPTING_FILE_SYSTEM;
367       else if (oid_tag == eku_ms_file_recovery)
368         string_id = IDS_CERT_EKU_MS_FILE_RECOVERY;
369       else if (oid_tag == eku_ms_windows_hardware_driver_verification)
370         string_id = IDS_CERT_EKU_MS_WINDOWS_HARDWARE_DRIVER_VERIFICATION;
371       else if (oid_tag == eku_ms_qualified_subordination)
372         string_id = IDS_CERT_EKU_MS_QUALIFIED_SUBORDINATION;
373       else if (oid_tag == eku_ms_key_recovery)
374         string_id = IDS_CERT_EKU_MS_KEY_RECOVERY;
375       else if (oid_tag == eku_ms_document_signing)
376         string_id = IDS_CERT_EKU_MS_DOCUMENT_SIGNING;
377       else if (oid_tag == eku_ms_lifetime_signing)
378         string_id = IDS_CERT_EKU_MS_LIFETIME_SIGNING;
379       else if (oid_tag == eku_ms_smart_card_logon)
380         string_id = IDS_CERT_EKU_MS_SMART_CARD_LOGON;
381       else if (oid_tag == eku_ms_key_recovery_agent)
382         string_id = IDS_CERT_EKU_MS_KEY_RECOVERY_AGENT;
383       else if (oid_tag == eku_netscape_international_step_up)
384         string_id = IDS_CERT_EKU_NETSCAPE_INTERNATIONAL_STEP_UP;
385       else if (oid_tag == cert_attribute_business_category)
386         string_id = IDS_CERT_OID_BUSINESS_CATEGORY;
387       else if (oid_tag == cert_attribute_ev_incorporation_country)
388         string_id = IDS_CERT_OID_EV_INCORPORATION_COUNTRY;
389       else
390         string_id = -1;
391       break;
392   }
393   if (string_id >= 0)
394     return l10n_util::GetStringUTF8(string_id);
395
396   return DumpOidString(oid);
397 }
398
399 // Get a display string from a Relative Distinguished Name.
400 std::string ProcessRDN(CERTRDN* rdn) {
401   std::string rv;
402
403   CERTAVA** avas = rdn->avas;
404   for (size_t i = 0; avas[i] != NULL; ++i) {
405     rv += GetOIDText(&avas[i]->type);
406     SECItem* decode_item = CERT_DecodeAVAValue(&avas[i]->value);
407     if (decode_item) {
408       // TODO(mattm): Pass decode_item to CERT_RFC1485_EscapeAndQuote.
409       rv += " = ";
410       std::string value(reinterpret_cast<char*>(decode_item->data),
411                         decode_item->len);
412       if (SECOID_FindOIDTag(&avas[i]->type) == SEC_OID_AVA_COMMON_NAME)
413         value = x509_certificate_model::ProcessIDN(value);
414       rv += value;
415       SECITEM_FreeItem(decode_item, PR_TRUE);
416     }
417     rv += '\n';
418   }
419
420   return rv;
421 }
422
423 std::string ProcessName(CERTName* name) {
424   std::string rv;
425   CERTRDN** last_rdn;
426
427   // Find last non-NULL rdn.
428   for (last_rdn = name->rdns; last_rdn[0]; last_rdn++) {}
429   last_rdn--;
430
431   for (CERTRDN** rdn = last_rdn; rdn >= name->rdns; rdn--)
432     rv += ProcessRDN(*rdn);
433   return rv;
434 }
435
436 std::string ProcessBasicConstraints(SECItem* extension_data) {
437   CERTBasicConstraints value;
438   value.pathLenConstraint = -1;
439   if (CERT_DecodeBasicConstraintValue(&value, extension_data) != SECSuccess)
440     return ProcessRawBytes(extension_data);
441
442   std::string rv;
443   if (value.isCA)
444     rv = l10n_util::GetStringUTF8(IDS_CERT_X509_BASIC_CONSTRAINT_IS_CA);
445   else
446     rv = l10n_util::GetStringUTF8(IDS_CERT_X509_BASIC_CONSTRAINT_IS_NOT_CA);
447   rv += '\n';
448   if (value.pathLenConstraint != -1) {
449     string16 depth;
450     if (value.pathLenConstraint == CERT_UNLIMITED_PATH_CONSTRAINT) {
451       depth = l10n_util::GetStringUTF16(
452           IDS_CERT_X509_BASIC_CONSTRAINT_PATH_LEN_UNLIMITED);
453     } else {
454       depth = base::FormatNumber(value.pathLenConstraint);
455     }
456     rv += l10n_util::GetStringFUTF8(IDS_CERT_X509_BASIC_CONSTRAINT_PATH_LEN,
457                                     depth);
458   }
459   return rv;
460 }
461
462 std::string ProcessGeneralName(PRArenaPool* arena,
463                                CERTGeneralName* current) {
464   DCHECK(current);
465
466   std::string key;
467   std::string value;
468
469   switch (current->type) {
470     case certOtherName: {
471       key = GetOIDText(&current->name.OthName.oid);
472       SECOidTag oid_tag = SECOID_FindOIDTag(&current->name.OthName.oid);
473       if (oid_tag == ms_nt_principal_name) {
474         // The type of this name is apparently nowhere explicitly
475         // documented. However, in the generated templates, it is always
476         // UTF-8. So try to decode this as UTF-8; if that fails, dump the
477         // raw data.
478         SECItem decoded;
479         if (SEC_ASN1DecodeItem(arena, &decoded,
480                                SEC_ASN1_GET(SEC_UTF8StringTemplate),
481                                &current->name.OthName.name) == SECSuccess) {
482           value = std::string(reinterpret_cast<char*>(decoded.data),
483                               decoded.len);
484         } else {
485           value = ProcessRawBytes(&current->name.OthName.name);
486         }
487         break;
488       } else if (oid_tag == ms_ntds_replication) {
489         // This should be a 16-byte GUID.
490         SECItem guid;
491         if (SEC_ASN1DecodeItem(arena, &guid,
492                                SEC_ASN1_GET(SEC_OctetStringTemplate),
493                                &current->name.OthName.name) == SECSuccess &&
494             guid.len == 16) {
495           unsigned char* d = guid.data;
496           base::SStringPrintf(
497               &value,
498               "{%.2x%.2x%.2x%.2x-%.2x%.2x-%.2x%.2x-"
499               "%.2x%.2x-%.2x%.2x%.2x%.2x%.2x%.2x}",
500               d[3], d[2], d[1], d[0], d[5], d[4], d[7], d[6],
501               d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
502         } else {
503           value = ProcessRawBytes(&current->name.OthName.name);
504         }
505       } else {
506         value = ProcessRawBytes(&current->name.OthName.name);
507       }
508       break;
509     }
510     case certRFC822Name:
511       key = l10n_util::GetStringUTF8(IDS_CERT_GENERAL_NAME_RFC822_NAME);
512       value = std::string(reinterpret_cast<char*>(current->name.other.data),
513                           current->name.other.len);
514       break;
515     case certDNSName:
516       key = l10n_util::GetStringUTF8(IDS_CERT_GENERAL_NAME_DNS_NAME);
517       value = std::string(reinterpret_cast<char*>(current->name.other.data),
518                           current->name.other.len);
519       value = x509_certificate_model::ProcessIDN(value);
520       break;
521     case certX400Address:
522       key = l10n_util::GetStringUTF8(IDS_CERT_GENERAL_NAME_X400_ADDRESS);
523       value = ProcessRawBytes(&current->name.other);
524       break;
525     case certDirectoryName:
526       key = l10n_util::GetStringUTF8(IDS_CERT_GENERAL_NAME_DIRECTORY_NAME);
527       value = ProcessName(&current->name.directoryName);
528       break;
529     case certEDIPartyName:
530       key = l10n_util::GetStringUTF8(IDS_CERT_GENERAL_NAME_EDI_PARTY_NAME);
531       value = ProcessRawBytes(&current->name.other);
532       break;
533     case certURI:
534       key = l10n_util::GetStringUTF8(IDS_CERT_GENERAL_NAME_URI);
535       value = std::string(reinterpret_cast<char*>(current->name.other.data),
536                           current->name.other.len);
537       break;
538     case certIPAddress: {
539       key = l10n_util::GetStringUTF8(IDS_CERT_GENERAL_NAME_IP_ADDRESS);
540       net::IPAddressNumber ip(
541           current->name.other.data,
542           current->name.other.data + current->name.other.len);
543       value = net::IPEndPoint(ip, 0).ToStringWithoutPort();
544       if (value.empty()) {
545         // Invalid IP address.
546         value = ProcessRawBytes(&current->name.other);
547       }
548       break;
549     }
550     case certRegisterID:
551       key = l10n_util::GetStringUTF8(IDS_CERT_GENERAL_NAME_REGISTERED_ID);
552       value = DumpOidString(&current->name.other);
553       break;
554   }
555   std::string rv(l10n_util::GetStringFUTF8(IDS_CERT_UNKNOWN_OID_INFO_FORMAT,
556                                            UTF8ToUTF16(key),
557                                            UTF8ToUTF16(value)));
558   rv += '\n';
559   return rv;
560 }
561
562 std::string ProcessGeneralNames(PRArenaPool* arena,
563                                 CERTGeneralName* name_list) {
564   std::string rv;
565   CERTGeneralName* current = name_list;
566
567   do {
568     std::string text = ProcessGeneralName(arena, current);
569     if (text.empty())
570       break;
571     rv += text;
572     current = CERT_GetNextGeneralName(current);
573   } while (current != name_list);
574   return rv;
575 }
576
577 std::string ProcessAltName(SECItem* extension_data) {
578   CERTGeneralName* name_list;
579
580   crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
581   CHECK(arena.get());
582
583   name_list = CERT_DecodeAltNameExtension(arena.get(), extension_data);
584   if (!name_list)
585     return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR);
586
587   return ProcessGeneralNames(arena.get(), name_list);
588 }
589
590 std::string ProcessSubjectKeyId(SECItem* extension_data) {
591   SECItem decoded;
592   crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
593   CHECK(arena.get());
594
595   std::string rv;
596   if (SEC_QuickDERDecodeItem(arena.get(), &decoded,
597                              SEC_ASN1_GET(SEC_OctetStringTemplate),
598                              extension_data) != SECSuccess) {
599     rv = l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR);
600     return rv;
601   }
602
603   rv = l10n_util::GetStringFUTF8(IDS_CERT_KEYID_FORMAT,
604                                  ASCIIToUTF16(ProcessRawBytes(&decoded)));
605   return rv;
606 }
607
608 std::string ProcessAuthKeyId(SECItem* extension_data) {
609   CERTAuthKeyID* ret;
610   crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
611   std::string rv;
612
613   CHECK(arena.get());
614
615   ret = CERT_DecodeAuthKeyID(arena.get(), extension_data);
616
617   if (ret->keyID.len > 0) {
618     rv += l10n_util::GetStringFUTF8(IDS_CERT_KEYID_FORMAT,
619                                     ASCIIToUTF16(ProcessRawBytes(&ret->keyID)));
620     rv += '\n';
621   }
622
623   if (ret->authCertIssuer) {
624     rv += l10n_util::GetStringFUTF8(
625         IDS_CERT_ISSUER_FORMAT,
626         UTF8ToUTF16(ProcessGeneralNames(arena.get(), ret->authCertIssuer)));
627     rv += '\n';
628   }
629
630   if (ret->authCertSerialNumber.len > 0) {
631     rv += l10n_util::GetStringFUTF8(
632         IDS_CERT_SERIAL_NUMBER_FORMAT,
633         ASCIIToUTF16(ProcessRawBytes(&ret->authCertSerialNumber)));
634     rv += '\n';
635   }
636
637   return rv;
638 }
639
640 std::string ProcessUserNotice(SECItem* der_notice) {
641   CERTUserNotice* notice = CERT_DecodeUserNotice(der_notice);
642   if (!notice)
643     return ProcessRawBytes(der_notice);
644
645   std::string rv;
646   if (notice->noticeReference.organization.len != 0) {
647     switch (notice->noticeReference.organization.type) {
648       case siAsciiString:
649       case siVisibleString:
650       case siUTF8String:
651         rv += std::string(
652             reinterpret_cast<char*>(notice->noticeReference.organization.data),
653             notice->noticeReference.organization.len);
654         break;
655       case siBMPString:
656         rv += ProcessBMPString(&notice->noticeReference.organization);
657         break;
658       default:
659         break;
660     }
661     rv += " - ";
662     SECItem** itemList = notice->noticeReference.noticeNumbers;
663     while (*itemList) {
664       unsigned long number;
665       if (SEC_ASN1DecodeInteger(*itemList, &number) == SECSuccess) {
666         if (itemList != notice->noticeReference.noticeNumbers)
667           rv += ", ";
668         rv += '#';
669         rv += UTF16ToUTF8(base::UintToString16(number));
670       }
671       itemList++;
672     }
673   }
674   if (notice->displayText.len != 0) {
675     rv += "\n    ";
676     switch (notice->displayText.type) {
677       case siAsciiString:
678       case siVisibleString:
679       case siUTF8String:
680         rv += std::string(reinterpret_cast<char*>(notice->displayText.data),
681                           notice->displayText.len);
682         break;
683       case siBMPString:
684         rv += ProcessBMPString(&notice->displayText);
685         break;
686       default:
687         break;
688     }
689   }
690
691   CERT_DestroyUserNotice(notice);
692   return rv;
693 }
694
695 std::string ProcessCertificatePolicies(SECItem* extension_data) {
696   std::string rv;
697
698   CERTCertificatePolicies* policies = CERT_DecodeCertificatePoliciesExtension(
699       extension_data);
700   if (!policies)
701     return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR);
702
703   CERTPolicyInfo** policyInfos = policies->policyInfos;
704   while (*policyInfos) {
705     CERTPolicyInfo* policyInfo = *policyInfos++;
706     std::string key = GetOIDText(&policyInfo->policyID);
707
708     // If we have policy qualifiers, display the oid text
709     // with a ':', otherwise just put the oid text and a newline.
710     // TODO(mattm): Add extra note if this is the ev oid?  (It's a bit
711     // complicated, since we don't want to do the EV check synchronously.)
712     if (policyInfo->policyQualifiers) {
713       rv += l10n_util::GetStringFUTF8(IDS_CERT_MULTILINE_INFO_START_FORMAT,
714                                       UTF8ToUTF16(key));
715     } else {
716       rv += key;
717     }
718     rv += '\n';
719
720     if (policyInfo->policyQualifiers) {
721       // Add all qualifiers on separate lines, indented.
722       CERTPolicyQualifier** policyQualifiers = policyInfo->policyQualifiers;
723       while (*policyQualifiers != NULL) {
724         rv += "  ";
725
726         CERTPolicyQualifier* policyQualifier = *policyQualifiers++;
727         rv += l10n_util::GetStringFUTF8(
728             IDS_CERT_MULTILINE_INFO_START_FORMAT,
729             UTF8ToUTF16(GetOIDText(&policyQualifier->qualifierID)));
730         switch(policyQualifier->oid) {
731           case SEC_OID_PKIX_CPS_POINTER_QUALIFIER:
732             rv += "    ";
733             /* The CPS pointer ought to be the cPSuri alternative
734                of the Qualifier choice. */
735             rv += ProcessIA5String(&policyQualifier->qualifierValue);
736             break;
737           case SEC_OID_PKIX_USER_NOTICE_QUALIFIER:
738             rv += ProcessUserNotice(&policyQualifier->qualifierValue);
739             break;
740           default:
741             rv += ProcessRawBytes(&policyQualifier->qualifierValue);
742             break;
743         }
744         rv += '\n';
745       }
746     }
747   }
748
749   CERT_DestroyCertificatePoliciesExtension(policies);
750   return rv;
751 }
752
753 std::string ProcessCrlDistPoints(SECItem* extension_data) {
754   std::string rv;
755   CERTCrlDistributionPoints* crldp;
756   CRLDistributionPoint** points;
757   CRLDistributionPoint* point;
758   bool comma;
759
760   static const struct {
761     int reason;
762     int string_id;
763   } reason_string_map[] = {
764     {RF_UNUSED, IDS_CERT_REVOCATION_REASON_UNUSED},
765     {RF_KEY_COMPROMISE, IDS_CERT_REVOCATION_REASON_KEY_COMPROMISE},
766     {RF_CA_COMPROMISE, IDS_CERT_REVOCATION_REASON_CA_COMPROMISE},
767     {RF_AFFILIATION_CHANGED, IDS_CERT_REVOCATION_REASON_AFFILIATION_CHANGED},
768     {RF_SUPERSEDED, IDS_CERT_REVOCATION_REASON_SUPERSEDED},
769     {RF_CESSATION_OF_OPERATION,
770      IDS_CERT_REVOCATION_REASON_CESSATION_OF_OPERATION},
771     {RF_CERTIFICATE_HOLD, IDS_CERT_REVOCATION_REASON_CERTIFICATE_HOLD},
772   };
773
774   crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
775   CHECK(arena.get());
776
777   crldp = CERT_DecodeCRLDistributionPoints(arena.get(), extension_data);
778   if (!crldp || !crldp->distPoints) {
779     rv = l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR);
780     return rv;
781   }
782
783   for (points = crldp->distPoints; *points; ++points) {
784     point = *points;
785     switch (point->distPointType) {
786       case generalName:
787         // generalName is a typo in upstream NSS; fullName is actually a
788         // GeneralNames (SEQUENCE OF GeneralName). See Mozilla Bug #615100.
789         rv += ProcessGeneralNames(arena.get(), point->distPoint.fullName);
790         break;
791       case relativeDistinguishedName:
792         rv += ProcessRDN(&point->distPoint.relativeName);
793         break;
794     }
795     if (point->reasons.len) {
796       rv += ' ';
797       comma = false;
798       for (size_t i = 0; i < ARRAYSIZE_UNSAFE(reason_string_map); ++i) {
799         if (point->reasons.data[0] & reason_string_map[i].reason) {
800           if (comma)
801             rv += ',';
802           rv += l10n_util::GetStringUTF8(reason_string_map[i].string_id);
803           comma = true;
804         }
805       }
806       rv += '\n';
807     }
808     if (point->crlIssuer) {
809       rv += l10n_util::GetStringFUTF8(
810           IDS_CERT_ISSUER_FORMAT,
811           UTF8ToUTF16(ProcessGeneralNames(arena.get(), point->crlIssuer)));
812     }
813   }
814   return rv;
815 }
816
817 std::string ProcessAuthInfoAccess(SECItem* extension_data) {
818   std::string rv;
819   CERTAuthInfoAccess** aia;
820   CERTAuthInfoAccess* desc;
821   crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
822   CHECK(arena.get());
823
824   aia = CERT_DecodeAuthInfoAccessExtension(arena.get(), extension_data);
825   if (aia == NULL)
826     return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR);
827
828   while (*aia != NULL) {
829     desc = *aia++;
830     string16 location_str = UTF8ToUTF16(ProcessGeneralName(arena.get(),
831                                                            desc->location));
832     switch (SECOID_FindOIDTag(&desc->method)) {
833     case SEC_OID_PKIX_OCSP:
834       rv += l10n_util::GetStringFUTF8(IDS_CERT_OCSP_RESPONDER_FORMAT,
835                                       location_str);
836       break;
837     case SEC_OID_PKIX_CA_ISSUERS:
838       rv += l10n_util::GetStringFUTF8(IDS_CERT_CA_ISSUERS_FORMAT,
839                                       location_str);
840       break;
841     default:
842       rv += l10n_util::GetStringFUTF8(IDS_CERT_UNKNOWN_OID_INFO_FORMAT,
843                                       UTF8ToUTF16(GetOIDText(&desc->method)),
844                                       location_str);
845       break;
846     }
847   }
848   return rv;
849 }
850
851 std::string ProcessIA5String(SECItem* extension_data) {
852   SECItem item;
853   if (SEC_ASN1DecodeItem(NULL, &item, SEC_ASN1_GET(SEC_IA5StringTemplate),
854                          extension_data) != SECSuccess)
855     return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR);
856   std::string rv((char*)item.data, item.len);  // ASCII data.
857   PORT_Free(item.data);
858   return rv;
859 }
860
861 std::string ProcessBMPString(SECItem* extension_data) {
862   std::string rv;
863   SECItem item;
864   crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
865   CHECK(arena.get());
866
867   if (SEC_ASN1DecodeItem(arena.get(), &item,
868                          SEC_ASN1_GET(SEC_BMPStringTemplate), extension_data) ==
869       SECSuccess)
870     rv = BMPtoUTF8(arena.get(), item.data, item.len);
871   return rv;
872 }
873
874 struct MaskIdPair {
875   unsigned int mask;
876   int string_id;
877 };
878
879 static std::string ProcessBitField(SECItem* bitfield,
880                                    const MaskIdPair* string_map,
881                                    size_t len,
882                                    char separator) {
883   unsigned int bits = 0;
884   std::string rv;
885   for (size_t i = 0; i * 8 < bitfield->len && i < sizeof(bits); ++i)
886     bits |= bitfield->data[i] << (i * 8);
887   for (size_t i = 0; i < len; ++i) {
888     if (bits & string_map[i].mask) {
889       if (!rv.empty())
890         rv += separator;
891       rv += l10n_util::GetStringUTF8(string_map[i].string_id);
892     }
893   }
894   return rv;
895 }
896
897 static std::string ProcessBitStringExtension(SECItem* extension_data,
898                                              const MaskIdPair* string_map,
899                                              size_t len,
900                                              char separator) {
901   SECItem decoded;
902   decoded.type = siBuffer;
903   decoded.data = NULL;
904   decoded.len  = 0;
905   if (SEC_ASN1DecodeItem(NULL, &decoded, SEC_ASN1_GET(SEC_BitStringTemplate),
906                          extension_data) != SECSuccess)
907     return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR);
908   std::string rv = ProcessBitField(&decoded, string_map, len, separator);
909   PORT_Free(decoded.data);
910   return rv;
911 }
912
913 std::string ProcessNSCertTypeExtension(SECItem* extension_data) {
914   static const MaskIdPair usage_string_map[] = {
915     {NS_CERT_TYPE_SSL_CLIENT, IDS_CERT_USAGE_SSL_CLIENT},
916     {NS_CERT_TYPE_SSL_SERVER, IDS_CERT_USAGE_SSL_SERVER},
917     {NS_CERT_TYPE_EMAIL, IDS_CERT_EXT_NS_CERT_TYPE_EMAIL},
918     {NS_CERT_TYPE_OBJECT_SIGNING, IDS_CERT_USAGE_OBJECT_SIGNER},
919     {NS_CERT_TYPE_SSL_CA, IDS_CERT_USAGE_SSL_CA},
920     {NS_CERT_TYPE_EMAIL_CA, IDS_CERT_EXT_NS_CERT_TYPE_EMAIL_CA},
921     {NS_CERT_TYPE_OBJECT_SIGNING_CA, IDS_CERT_USAGE_OBJECT_SIGNER},
922   };
923   return ProcessBitStringExtension(extension_data, usage_string_map,
924                                    ARRAYSIZE_UNSAFE(usage_string_map), '\n');
925 }
926
927 static const MaskIdPair key_usage_string_map[] = {
928   {KU_DIGITAL_SIGNATURE, IDS_CERT_X509_KEY_USAGE_SIGNING},
929   {KU_NON_REPUDIATION, IDS_CERT_X509_KEY_USAGE_NONREP},
930   {KU_KEY_ENCIPHERMENT, IDS_CERT_X509_KEY_USAGE_ENCIPHERMENT},
931   {KU_DATA_ENCIPHERMENT, IDS_CERT_X509_KEY_USAGE_DATA_ENCIPHERMENT},
932   {KU_KEY_AGREEMENT, IDS_CERT_X509_KEY_USAGE_KEY_AGREEMENT},
933   {KU_KEY_CERT_SIGN, IDS_CERT_X509_KEY_USAGE_CERT_SIGNER},
934   {KU_CRL_SIGN, IDS_CERT_X509_KEY_USAGE_CRL_SIGNER},
935   {KU_ENCIPHER_ONLY, IDS_CERT_X509_KEY_USAGE_ENCIPHER_ONLY},
936   // NSS is missing a flag for dechiperOnly, see:
937   // https://bugzilla.mozilla.org/show_bug.cgi?id=549952
938 };
939
940 std::string ProcessKeyUsageBitString(SECItem* bitstring, char sep) {
941   return ProcessBitField(bitstring, key_usage_string_map,
942                          arraysize(key_usage_string_map), sep);
943 }
944
945 std::string ProcessKeyUsageExtension(SECItem* extension_data) {
946   return ProcessBitStringExtension(extension_data, key_usage_string_map,
947                                    arraysize(key_usage_string_map), '\n');
948 }
949
950 std::string ProcessExtKeyUsage(SECItem* extension_data) {
951   std::string rv;
952   CERTOidSequence* extension_key_usage = NULL;
953   extension_key_usage = CERT_DecodeOidSequence(extension_data);
954   if (extension_key_usage == NULL)
955     return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR);
956
957   SECItem** oids;
958   SECItem* oid;
959   for (oids = extension_key_usage->oids; oids != NULL && *oids != NULL;
960        ++oids) {
961     oid = *oids;
962     std::string oid_dump = DumpOidString(oid);
963     std::string oid_text = GetOIDText(oid);
964
965     // If oid is one we recognize, oid_text will have a text description of the OID,
966     // which we display along with the oid_dump.  If we don't recognize the OID,
967     // GetOIDText will return the same value as DumpOidString, so just display
968     // the OID alone.
969     if (oid_dump == oid_text)
970       rv += oid_dump;
971     else
972       rv += l10n_util::GetStringFUTF8(IDS_CERT_EXT_KEY_USAGE_FORMAT,
973                                       UTF8ToUTF16(oid_text),
974                                       UTF8ToUTF16(oid_dump));
975     rv += '\n';
976   }
977   CERT_DestroyOidSequence(extension_key_usage);
978   return rv;
979 }
980
981 std::string ProcessExtensionData(SECOidTag oid_tag, SECItem* extension_data) {
982   // This (and its sub-functions) are based on the same-named functions in
983   // security/manager/ssl/src/nsNSSCertHelper.cpp.
984   switch (oid_tag) {
985     case SEC_OID_NS_CERT_EXT_CERT_TYPE:
986       return ProcessNSCertTypeExtension(extension_data);
987     case SEC_OID_X509_KEY_USAGE:
988       return ProcessKeyUsageExtension(extension_data);
989     case SEC_OID_X509_BASIC_CONSTRAINTS:
990       return ProcessBasicConstraints(extension_data);
991     case SEC_OID_X509_EXT_KEY_USAGE:
992       return ProcessExtKeyUsage(extension_data);
993     case SEC_OID_X509_ISSUER_ALT_NAME:
994     case SEC_OID_X509_SUBJECT_ALT_NAME:
995       return ProcessAltName(extension_data);
996     case SEC_OID_X509_SUBJECT_KEY_ID:
997       return ProcessSubjectKeyId(extension_data);
998     case SEC_OID_X509_AUTH_KEY_ID:
999       return ProcessAuthKeyId(extension_data);
1000     case SEC_OID_X509_CERTIFICATE_POLICIES:
1001       return ProcessCertificatePolicies(extension_data);
1002     case SEC_OID_X509_CRL_DIST_POINTS:
1003       return ProcessCrlDistPoints(extension_data);
1004     case SEC_OID_X509_AUTH_INFO_ACCESS:
1005       return ProcessAuthInfoAccess(extension_data);
1006     case SEC_OID_NS_CERT_EXT_BASE_URL:
1007     case SEC_OID_NS_CERT_EXT_REVOCATION_URL:
1008     case SEC_OID_NS_CERT_EXT_CA_REVOCATION_URL:
1009     case SEC_OID_NS_CERT_EXT_CA_CERT_URL:
1010     case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_URL:
1011     case SEC_OID_NS_CERT_EXT_CA_POLICY_URL:
1012     case SEC_OID_NS_CERT_EXT_HOMEPAGE_URL:
1013     case SEC_OID_NS_CERT_EXT_COMMENT:
1014     case SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME:
1015     case SEC_OID_NS_CERT_EXT_LOST_PASSWORD_URL:
1016       return ProcessIA5String(extension_data);
1017     default:
1018       if (oid_tag == ms_cert_ext_certtype)
1019         return ProcessBMPString(extension_data);
1020       return ProcessRawBytes(extension_data);
1021   }
1022 }
1023
1024 std::string ProcessSubjectPublicKeyInfo(CERTSubjectPublicKeyInfo* spki) {
1025   std::string rv;
1026   SECKEYPublicKey* key = SECKEY_ExtractPublicKey(spki);
1027   if (key) {
1028     switch (key->keyType) {
1029       case rsaKey: {
1030         rv = l10n_util::GetStringFUTF8(
1031             IDS_CERT_RSA_PUBLIC_KEY_DUMP_FORMAT,
1032             base::UintToString16(key->u.rsa.modulus.len * 8),
1033             UTF8ToUTF16(ProcessRawBytes(&key->u.rsa.modulus)),
1034             base::UintToString16(key->u.rsa.publicExponent.len * 8),
1035             UTF8ToUTF16(ProcessRawBytes(&key->u.rsa.publicExponent)));
1036         break;
1037       }
1038       default:
1039         rv = x509_certificate_model::ProcessRawBits(
1040             spki->subjectPublicKey.data, spki->subjectPublicKey.len);
1041         break;
1042     }
1043     SECKEY_DestroyPublicKey(key);
1044   }
1045   return rv;
1046 }
1047
1048 net::CertType GetCertType(CERTCertificate *cert) {
1049   CERTCertTrust trust = {0};
1050   CERT_GetCertTrust(cert, &trust);
1051
1052   unsigned all_flags = trust.sslFlags | trust.emailFlags |
1053       trust.objectSigningFlags;
1054
1055   if (cert->nickname && (all_flags & CERTDB_USER))
1056     return net::USER_CERT;
1057   if ((all_flags & CERTDB_VALID_CA) || CERT_IsCACert(cert, NULL))
1058     return net::CA_CERT;
1059   // TODO(mattm): http://crbug.com/128633.
1060   if (trust.sslFlags & CERTDB_TERMINAL_RECORD)
1061     return net::SERVER_CERT;
1062   return net::OTHER_CERT;
1063 }
1064
1065 }  // namespace mozilla_security_manager