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