1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
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/
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
14 * The Original Code is the Netscape security libraries.
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.
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>
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.
39 * ***** END LICENSE BLOCK ***** */
41 #include "chrome/third_party/mozilla_security_manager/nsNSSCertHelper.h"
46 #include <unicode/uidna.h>
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"
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.
65 #define CERTDB_TERMINAL_RECORD CERTDB_VALID_PEER
70 std::string
BMPtoUTF8(PRArenaPool
* arena
, unsigned char* data
,
73 return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR
);
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
);
83 SECOidTag
RegisterDynamicOid(const char* oid_string
) {
84 SECOidTag rv
= SEC_OID_UNKNOWN
;
85 unsigned char buffer
[1024];
87 od
.oid
.type
= siDEROID
;
89 od
.oid
.len
= sizeof(buffer
);
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
;
97 rv
= SECOID_AddEntry(&od
);
99 DCHECK_NE(rv
, SEC_OID_UNKNOWN
) << oid_string
;
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
);
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
;
130 class DynamicOidRegisterer
{
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");
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");
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");
166 static base::LazyInstance
<DynamicOidRegisterer
>::Leaky
167 g_dynamic_oid_registerer
= LAZY_INSTANCE_INITIALIZER
;
171 namespace mozilla_security_manager
{
173 std::string
DumpOidString(SECItem
* oid
) {
174 char* pr_string
= CERT_GetOidString(oid
);
176 std::string rv
= pr_string
;
177 PR_smprintf_free(pr_string
);
181 return ProcessRawBytes(oid
);
184 std::string
GetOIDText(SECItem
* oid
) {
185 g_dynamic_oid_registerer
.Get();
188 SECOidTag oid_tag
= SECOID_FindOIDTag(oid
);
190 case SEC_OID_AVA_COMMON_NAME
:
191 string_id
= IDS_CERT_OID_AVA_COMMON_NAME
;
193 case SEC_OID_AVA_STATE_OR_PROVINCE
:
194 string_id
= IDS_CERT_OID_AVA_STATE_OR_PROVINCE
;
196 case SEC_OID_AVA_ORGANIZATION_NAME
:
197 string_id
= IDS_CERT_OID_AVA_ORGANIZATION_NAME
;
199 case SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME
:
200 string_id
= IDS_CERT_OID_AVA_ORGANIZATIONAL_UNIT_NAME
;
202 case SEC_OID_AVA_DN_QUALIFIER
:
203 string_id
= IDS_CERT_OID_AVA_DN_QUALIFIER
;
205 case SEC_OID_AVA_COUNTRY_NAME
:
206 string_id
= IDS_CERT_OID_AVA_COUNTRY_NAME
;
208 case SEC_OID_AVA_SERIAL_NUMBER
:
209 string_id
= IDS_CERT_OID_AVA_SERIAL_NUMBER
;
211 case SEC_OID_AVA_LOCALITY
:
212 string_id
= IDS_CERT_OID_AVA_LOCALITY
;
215 string_id
= IDS_CERT_OID_AVA_DC
;
217 case SEC_OID_RFC1274_MAIL
:
218 string_id
= IDS_CERT_OID_RFC1274_MAIL
;
220 case SEC_OID_RFC1274_UID
:
221 string_id
= IDS_CERT_OID_RFC1274_UID
;
223 case SEC_OID_PKCS9_EMAIL_ADDRESS
:
224 string_id
= IDS_CERT_OID_PKCS9_EMAIL_ADDRESS
;
226 case SEC_OID_PKCS1_RSA_ENCRYPTION
:
227 string_id
= IDS_CERT_OID_PKCS1_RSA_ENCRYPTION
;
229 case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION
:
230 string_id
= IDS_CERT_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION
;
232 case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION
:
233 string_id
= IDS_CERT_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION
;
235 case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION
:
236 string_id
= IDS_CERT_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION
;
238 case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION
:
239 string_id
= IDS_CERT_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION
;
241 case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION
:
242 string_id
= IDS_CERT_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION
;
244 case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION
:
245 string_id
= IDS_CERT_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION
;
247 case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION
:
248 string_id
= IDS_CERT_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION
;
250 case SEC_OID_NS_CERT_EXT_CERT_TYPE
:
251 string_id
= IDS_CERT_EXT_NS_CERT_TYPE
;
253 case SEC_OID_NS_CERT_EXT_BASE_URL
:
254 string_id
= IDS_CERT_EXT_NS_CERT_BASE_URL
;
256 case SEC_OID_NS_CERT_EXT_REVOCATION_URL
:
257 string_id
= IDS_CERT_EXT_NS_CERT_REVOCATION_URL
;
259 case SEC_OID_NS_CERT_EXT_CA_REVOCATION_URL
:
260 string_id
= IDS_CERT_EXT_NS_CA_REVOCATION_URL
;
262 case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_URL
:
263 string_id
= IDS_CERT_EXT_NS_CERT_RENEWAL_URL
;
265 case SEC_OID_NS_CERT_EXT_CA_POLICY_URL
:
266 string_id
= IDS_CERT_EXT_NS_CA_POLICY_URL
;
268 case SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME
:
269 string_id
= IDS_CERT_EXT_NS_SSL_SERVER_NAME
;
271 case SEC_OID_NS_CERT_EXT_COMMENT
:
272 string_id
= IDS_CERT_EXT_NS_COMMENT
;
274 case SEC_OID_NS_CERT_EXT_LOST_PASSWORD_URL
:
275 string_id
= IDS_CERT_EXT_NS_LOST_PASSWORD_URL
;
277 case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_TIME
:
278 string_id
= IDS_CERT_EXT_NS_CERT_RENEWAL_TIME
;
280 case SEC_OID_X509_SUBJECT_DIRECTORY_ATTR
:
281 string_id
= IDS_CERT_X509_SUBJECT_DIRECTORY_ATTR
;
283 case SEC_OID_X509_SUBJECT_KEY_ID
:
284 string_id
= IDS_CERT_X509_SUBJECT_KEYID
;
286 case SEC_OID_X509_KEY_USAGE
:
287 string_id
= IDS_CERT_X509_KEY_USAGE
;
289 case SEC_OID_X509_SUBJECT_ALT_NAME
:
290 string_id
= IDS_CERT_X509_SUBJECT_ALT_NAME
;
292 case SEC_OID_X509_ISSUER_ALT_NAME
:
293 string_id
= IDS_CERT_X509_ISSUER_ALT_NAME
;
295 case SEC_OID_X509_BASIC_CONSTRAINTS
:
296 string_id
= IDS_CERT_X509_BASIC_CONSTRAINTS
;
298 case SEC_OID_X509_NAME_CONSTRAINTS
:
299 string_id
= IDS_CERT_X509_NAME_CONSTRAINTS
;
301 case SEC_OID_X509_CRL_DIST_POINTS
:
302 string_id
= IDS_CERT_X509_CRL_DIST_POINTS
;
304 case SEC_OID_X509_CERTIFICATE_POLICIES
:
305 string_id
= IDS_CERT_X509_CERT_POLICIES
;
307 case SEC_OID_X509_POLICY_MAPPINGS
:
308 string_id
= IDS_CERT_X509_POLICY_MAPPINGS
;
310 case SEC_OID_X509_POLICY_CONSTRAINTS
:
311 string_id
= IDS_CERT_X509_POLICY_CONSTRAINTS
;
313 case SEC_OID_X509_AUTH_KEY_ID
:
314 string_id
= IDS_CERT_X509_AUTH_KEYID
;
316 case SEC_OID_X509_EXT_KEY_USAGE
:
317 string_id
= IDS_CERT_X509_EXT_KEY_USAGE
;
319 case SEC_OID_X509_AUTH_INFO_ACCESS
:
320 string_id
= IDS_CERT_X509_AUTH_INFO_ACCESS
;
322 case SEC_OID_EXT_KEY_USAGE_SERVER_AUTH
:
323 string_id
= IDS_CERT_EKU_TLS_WEB_SERVER_AUTHENTICATION
;
325 case SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH
:
326 string_id
= IDS_CERT_EKU_TLS_WEB_CLIENT_AUTHENTICATION
;
328 case SEC_OID_EXT_KEY_USAGE_CODE_SIGN
:
329 string_id
= IDS_CERT_EKU_CODE_SIGNING
;
331 case SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT
:
332 string_id
= IDS_CERT_EKU_EMAIL_PROTECTION
;
334 case SEC_OID_EXT_KEY_USAGE_TIME_STAMP
:
335 string_id
= IDS_CERT_EKU_TIME_STAMPING
;
337 case SEC_OID_OCSP_RESPONDER
:
338 string_id
= IDS_CERT_EKU_OCSP_SIGNING
;
340 case SEC_OID_PKIX_CPS_POINTER_QUALIFIER
:
341 string_id
= IDS_CERT_PKIX_CPS_POINTER_QUALIFIER
;
343 case SEC_OID_PKIX_USER_NOTICE_QUALIFIER
:
344 string_id
= IDS_CERT_PKIX_USER_NOTICE_QUALIFIER
;
346 case SEC_OID_UNKNOWN
:
350 // There are a billionty other OIDs we could add here. I tried to get the
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
;
400 return l10n_util::GetStringUTF8(string_id
);
402 return DumpOidString(oid
);
405 // Get a display string from a Relative Distinguished Name.
406 std::string
ProcessRDN(CERTRDN
* rdn
) {
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
);
414 // TODO(mattm): Pass decode_item to CERT_RFC1485_EscapeAndQuote.
416 std::string
value(reinterpret_cast<char*>(decode_item
->data
),
418 if (SECOID_FindOIDTag(&avas
[i
]->type
) == SEC_OID_AVA_COMMON_NAME
)
419 value
= x509_certificate_model::ProcessIDN(value
);
421 SECITEM_FreeItem(decode_item
, PR_TRUE
);
429 std::string
ProcessName(CERTName
* name
) {
433 // Find last non-NULL rdn.
434 for (last_rdn
= name
->rdns
; last_rdn
[0]; last_rdn
++) {}
437 for (CERTRDN
** rdn
= last_rdn
; rdn
>= name
->rdns
; rdn
--)
438 rv
+= ProcessRDN(*rdn
);
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
);
450 rv
= l10n_util::GetStringUTF8(IDS_CERT_X509_BASIC_CONSTRAINT_IS_CA
);
452 rv
= l10n_util::GetStringUTF8(IDS_CERT_X509_BASIC_CONSTRAINT_IS_NOT_CA
);
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
);
460 depth
= base::FormatNumber(value
.pathLenConstraint
);
462 rv
+= l10n_util::GetStringFUTF8(IDS_CERT_X509_BASIC_CONSTRAINT_PATH_LEN
,
468 std::string
ProcessGeneralName(PRArenaPool
* arena
,
469 CERTGeneralName
* current
) {
475 switch (current
->type
) {
476 case certOtherName
: {
477 key
= GetOIDText(¤t
->name
.OthName
.oid
);
478 // g_dynamic_oid_registerer.Get() will have been run by GetOIDText.
479 SECOidTag oid_tag
= SECOID_FindOIDTag(¤t
->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
486 if (SEC_ASN1DecodeItem(arena
, &decoded
,
487 SEC_ASN1_GET(SEC_UTF8StringTemplate
),
488 ¤t
->name
.OthName
.name
) == SECSuccess
) {
489 value
= std::string(reinterpret_cast<char*>(decoded
.data
),
492 value
= ProcessRawBytes(¤t
->name
.OthName
.name
);
495 } else if (oid_tag
== ms_ntds_replication
) {
496 // This should be a 16-byte GUID.
498 if (SEC_ASN1DecodeItem(arena
, &guid
,
499 SEC_ASN1_GET(SEC_OctetStringTemplate
),
500 ¤t
->name
.OthName
.name
) == SECSuccess
&&
502 unsigned char* d
= guid
.data
;
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]);
510 value
= ProcessRawBytes(¤t
->name
.OthName
.name
);
513 value
= ProcessRawBytes(¤t
->name
.OthName
.name
);
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
);
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
);
528 case certX400Address
:
529 key
= l10n_util::GetStringUTF8(IDS_CERT_GENERAL_NAME_X400_ADDRESS
);
530 value
= ProcessRawBytes(¤t
->name
.other
);
532 case certDirectoryName
:
533 key
= l10n_util::GetStringUTF8(IDS_CERT_GENERAL_NAME_DIRECTORY_NAME
);
534 value
= ProcessName(¤t
->name
.directoryName
);
536 case certEDIPartyName
:
537 key
= l10n_util::GetStringUTF8(IDS_CERT_GENERAL_NAME_EDI_PARTY_NAME
);
538 value
= ProcessRawBytes(¤t
->name
.other
);
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
);
545 case certIPAddress
: {
546 key
= l10n_util::GetStringUTF8(IDS_CERT_GENERAL_NAME_IP_ADDRESS
);
548 net::IPAddressNumber
ip(
549 current
->name
.other
.data
,
550 current
->name
.other
.data
+ current
->name
.other
.len
);
552 if (net::GetAddressFamily(ip
) != net::ADDRESS_FAMILY_UNSPECIFIED
) {
553 value
= net::IPAddressToString(ip
);
555 // Invalid IP address.
556 value
= ProcessRawBytes(¤t
->name
.other
);
561 key
= l10n_util::GetStringUTF8(IDS_CERT_GENERAL_NAME_REGISTERED_ID
);
562 value
= DumpOidString(¤t
->name
.other
);
565 std::string
rv(l10n_util::GetStringFUTF8(IDS_CERT_UNKNOWN_OID_INFO_FORMAT
,
566 base::UTF8ToUTF16(key
),
567 base::UTF8ToUTF16(value
)));
572 std::string
ProcessGeneralNames(PRArenaPool
* arena
,
573 CERTGeneralName
* name_list
) {
575 CERTGeneralName
* current
= name_list
;
578 std::string text
= ProcessGeneralName(arena
, current
);
582 current
= CERT_GetNextGeneralName(current
);
583 } while (current
!= name_list
);
587 std::string
ProcessAltName(SECItem
* extension_data
) {
588 CERTGeneralName
* name_list
;
590 crypto::ScopedPLArenaPool
arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE
));
593 name_list
= CERT_DecodeAltNameExtension(arena
.get(), extension_data
);
595 return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR
);
597 return ProcessGeneralNames(arena
.get(), name_list
);
600 std::string
ProcessSubjectKeyId(SECItem
* extension_data
) {
602 crypto::ScopedPLArenaPool
arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE
));
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
);
613 rv
= l10n_util::GetStringFUTF8(IDS_CERT_KEYID_FORMAT
,
614 base::ASCIIToUTF16(ProcessRawBytes(&decoded
)));
618 std::string
ProcessAuthKeyId(SECItem
* extension_data
) {
620 crypto::ScopedPLArenaPool
arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE
));
625 ret
= CERT_DecodeAuthKeyID(arena
.get(), extension_data
);
627 if (ret
->keyID
.len
> 0) {
628 rv
+= l10n_util::GetStringFUTF8(IDS_CERT_KEYID_FORMAT
,
630 ProcessRawBytes(&ret
->keyID
)));
634 if (ret
->authCertIssuer
) {
635 rv
+= l10n_util::GetStringFUTF8(
636 IDS_CERT_ISSUER_FORMAT
,
638 ProcessGeneralNames(arena
.get(), ret
->authCertIssuer
)));
642 if (ret
->authCertSerialNumber
.len
> 0) {
643 rv
+= l10n_util::GetStringFUTF8(
644 IDS_CERT_SERIAL_NUMBER_FORMAT
,
645 base::ASCIIToUTF16(ProcessRawBytes(&ret
->authCertSerialNumber
)));
652 std::string
ProcessUserNotice(SECItem
* der_notice
) {
653 CERTUserNotice
* notice
= CERT_DecodeUserNotice(der_notice
);
655 return ProcessRawBytes(der_notice
);
658 if (notice
->noticeReference
.organization
.len
!= 0) {
659 switch (notice
->noticeReference
.organization
.type
) {
661 case siVisibleString
:
664 reinterpret_cast<char*>(notice
->noticeReference
.organization
.data
),
665 notice
->noticeReference
.organization
.len
);
668 rv
+= ProcessBMPString(¬ice
->noticeReference
.organization
);
674 SECItem
** itemList
= notice
->noticeReference
.noticeNumbers
;
676 unsigned long number
;
677 if (SEC_ASN1DecodeInteger(*itemList
, &number
) == SECSuccess
) {
678 if (itemList
!= notice
->noticeReference
.noticeNumbers
)
681 rv
+= base::UTF16ToUTF8(base::UintToString16(number
));
686 if (notice
->displayText
.len
!= 0) {
688 switch (notice
->displayText
.type
) {
690 case siVisibleString
:
692 rv
+= std::string(reinterpret_cast<char*>(notice
->displayText
.data
),
693 notice
->displayText
.len
);
696 rv
+= ProcessBMPString(¬ice
->displayText
);
703 CERT_DestroyUserNotice(notice
);
707 std::string
ProcessCertificatePolicies(SECItem
* extension_data
) {
710 CERTCertificatePolicies
* policies
= CERT_DecodeCertificatePoliciesExtension(
713 return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR
);
715 CERTPolicyInfo
** policyInfos
= policies
->policyInfos
;
716 while (*policyInfos
) {
717 CERTPolicyInfo
* policyInfo
= *policyInfos
++;
718 std::string key
= GetOIDText(&policyInfo
->policyID
);
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
));
732 if (policyInfo
->policyQualifiers
) {
733 // Add all qualifiers on separate lines, indented.
734 CERTPolicyQualifier
** policyQualifiers
= policyInfo
->policyQualifiers
;
735 while (*policyQualifiers
!= NULL
) {
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
:
745 /* The CPS pointer ought to be the cPSuri alternative
746 of the Qualifier choice. */
747 rv
+= ProcessIA5String(&policyQualifier
->qualifierValue
);
749 case SEC_OID_PKIX_USER_NOTICE_QUALIFIER
:
750 rv
+= ProcessUserNotice(&policyQualifier
->qualifierValue
);
753 rv
+= ProcessRawBytes(&policyQualifier
->qualifierValue
);
761 CERT_DestroyCertificatePoliciesExtension(policies
);
765 std::string
ProcessCrlDistPoints(SECItem
* extension_data
) {
767 CERTCrlDistributionPoints
* crldp
;
768 CRLDistributionPoint
** points
;
769 CRLDistributionPoint
* point
;
772 static const struct {
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
},
786 crypto::ScopedPLArenaPool
arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE
));
789 crldp
= CERT_DecodeCRLDistributionPoints(arena
.get(), extension_data
);
790 if (!crldp
|| !crldp
->distPoints
) {
791 rv
= l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR
);
795 for (points
= crldp
->distPoints
; *points
; ++points
) {
797 switch (point
->distPointType
) {
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
);
803 case relativeDistinguishedName
:
804 rv
+= ProcessRDN(&point
->distPoint
.relativeName
);
807 if (point
->reasons
.len
) {
810 for (size_t i
= 0; i
< arraysize(reason_string_map
); ++i
) {
811 if (point
->reasons
.data
[0] & reason_string_map
[i
].reason
) {
814 rv
+= l10n_util::GetStringUTF8(reason_string_map
[i
].string_id
);
820 if (point
->crlIssuer
) {
821 rv
+= l10n_util::GetStringFUTF8(
822 IDS_CERT_ISSUER_FORMAT
,
824 ProcessGeneralNames(arena
.get(), point
->crlIssuer
)));
830 std::string
ProcessAuthInfoAccess(SECItem
* extension_data
) {
832 CERTAuthInfoAccess
** aia
;
833 CERTAuthInfoAccess
* desc
;
834 crypto::ScopedPLArenaPool
arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE
));
837 aia
= CERT_DecodeAuthInfoAccessExtension(arena
.get(), extension_data
);
839 return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR
);
841 while (*aia
!= NULL
) {
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
,
850 case SEC_OID_PKIX_CA_ISSUERS
:
851 rv
+= l10n_util::GetStringFUTF8(IDS_CERT_CA_ISSUERS_FORMAT
,
855 rv
+= l10n_util::GetStringFUTF8(IDS_CERT_UNKNOWN_OID_INFO_FORMAT
,
857 GetOIDText(&desc
->method
)),
865 std::string
ProcessIA5String(SECItem
* extension_data
) {
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
);
875 std::string
ProcessBMPString(SECItem
* extension_data
) {
878 crypto::ScopedPLArenaPool
arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE
));
881 if (SEC_ASN1DecodeItem(arena
.get(), &item
,
882 SEC_ASN1_GET(SEC_BMPStringTemplate
), extension_data
) ==
884 rv
= BMPtoUTF8(arena
.get(), item
.data
, item
.len
);
893 static std::string
ProcessBitField(SECItem
* bitfield
,
894 const MaskIdPair
* string_map
,
897 unsigned int bits
= 0;
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
) {
905 rv
+= l10n_util::GetStringUTF8(string_map
[i
].string_id
);
911 static std::string
ProcessBitStringExtension(SECItem
* extension_data
,
912 const MaskIdPair
* string_map
,
916 decoded
.type
= siBuffer
;
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
);
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
},
937 return ProcessBitStringExtension(extension_data
, usage_string_map
,
938 arraysize(usage_string_map
), '\n');
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
954 std::string
ProcessKeyUsageBitString(SECItem
* bitstring
, char sep
) {
955 return ProcessBitField(bitstring
, key_usage_string_map
,
956 arraysize(key_usage_string_map
), sep
);
959 std::string
ProcessKeyUsageExtension(SECItem
* extension_data
) {
960 return ProcessBitStringExtension(extension_data
, key_usage_string_map
,
961 arraysize(key_usage_string_map
), '\n');
964 std::string
ProcessExtKeyUsage(SECItem
* extension_data
) {
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
);
973 for (oids
= extension_key_usage
->oids
; oids
!= NULL
&& *oids
!= NULL
;
976 std::string oid_dump
= DumpOidString(oid
);
977 std::string oid_text
= GetOIDText(oid
);
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
)
986 rv
+= l10n_util::GetStringFUTF8(IDS_CERT_EXT_KEY_USAGE_FORMAT
,
987 base::UTF8ToUTF16(oid_text
),
988 base::UTF8ToUTF16(oid_dump
));
991 CERT_DestroyOidSequence(extension_key_usage
);
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
;
1000 // This (and its sub-functions) are based on the same-named functions in
1001 // security/manager/ssl/src/nsNSSCertHelper.cpp.
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
);
1036 if (oid_tag
== ms_cert_ext_certtype
)
1037 return ProcessBMPString(extension_data
);
1038 return ProcessRawBytes(extension_data
);
1042 std::string
ProcessSubjectPublicKeyInfo(CERTSubjectPublicKeyInfo
* spki
) {
1044 SECKEYPublicKey
* key
= SECKEY_ExtractPublicKey(spki
);
1046 switch (key
->keyType
) {
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
)));
1057 rv
= x509_certificate_model::ProcessRawBits(
1058 spki
->subjectPublicKey
.data
, spki
->subjectPublicKey
.len
);
1061 SECKEY_DestroyPublicKey(key
);
1066 net::CertType
GetCertType(CERTCertificate
*cert
) {
1067 CERTCertTrust trust
= {0};
1068 CERT_GetCertTrust(cert
, &trust
);
1070 unsigned all_flags
= trust
.sslFlags
| trust
.emailFlags
|
1071 trust
.objectSigningFlags
;
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
;
1083 } // namespace mozilla_security_manager