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/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"
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.
64 #define CERTDB_TERMINAL_RECORD CERTDB_VALID_PEER
69 std::string
BMPtoUTF8(PRArenaPool
* arena
, unsigned char* data
,
72 return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR
);
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
);
82 SECOidTag
RegisterDynamicOid(const char* oid_string
) {
83 SECOidTag rv
= SEC_OID_UNKNOWN
;
84 unsigned char buffer
[1024];
86 od
.oid
.type
= siDEROID
;
88 od
.oid
.len
= sizeof(buffer
);
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
;
96 rv
= SECOID_AddEntry(&od
);
98 DCHECK_NE(rv
, SEC_OID_UNKNOWN
) << oid_string
;
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
);
109 namespace mozilla_security_manager
{
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
;
133 void RegisterDynamicOids() {
134 if (ms_cert_ext_certtype
!= SEC_OID_UNKNOWN
)
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");
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");
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");
169 std::string
DumpOidString(SECItem
* oid
) {
170 char* pr_string
= CERT_GetOidString(oid
);
172 std::string rv
= pr_string
;
173 PR_smprintf_free(pr_string
);
177 return ProcessRawBytes(oid
);
180 std::string
GetOIDText(SECItem
* oid
) {
182 SECOidTag oid_tag
= SECOID_FindOIDTag(oid
);
184 case SEC_OID_AVA_COMMON_NAME
:
185 string_id
= IDS_CERT_OID_AVA_COMMON_NAME
;
187 case SEC_OID_AVA_STATE_OR_PROVINCE
:
188 string_id
= IDS_CERT_OID_AVA_STATE_OR_PROVINCE
;
190 case SEC_OID_AVA_ORGANIZATION_NAME
:
191 string_id
= IDS_CERT_OID_AVA_ORGANIZATION_NAME
;
193 case SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME
:
194 string_id
= IDS_CERT_OID_AVA_ORGANIZATIONAL_UNIT_NAME
;
196 case SEC_OID_AVA_DN_QUALIFIER
:
197 string_id
= IDS_CERT_OID_AVA_DN_QUALIFIER
;
199 case SEC_OID_AVA_COUNTRY_NAME
:
200 string_id
= IDS_CERT_OID_AVA_COUNTRY_NAME
;
202 case SEC_OID_AVA_SERIAL_NUMBER
:
203 string_id
= IDS_CERT_OID_AVA_SERIAL_NUMBER
;
205 case SEC_OID_AVA_LOCALITY
:
206 string_id
= IDS_CERT_OID_AVA_LOCALITY
;
209 string_id
= IDS_CERT_OID_AVA_DC
;
211 case SEC_OID_RFC1274_MAIL
:
212 string_id
= IDS_CERT_OID_RFC1274_MAIL
;
214 case SEC_OID_RFC1274_UID
:
215 string_id
= IDS_CERT_OID_RFC1274_UID
;
217 case SEC_OID_PKCS9_EMAIL_ADDRESS
:
218 string_id
= IDS_CERT_OID_PKCS9_EMAIL_ADDRESS
;
220 case SEC_OID_PKCS1_RSA_ENCRYPTION
:
221 string_id
= IDS_CERT_OID_PKCS1_RSA_ENCRYPTION
;
223 case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION
:
224 string_id
= IDS_CERT_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION
;
226 case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION
:
227 string_id
= IDS_CERT_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION
;
229 case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION
:
230 string_id
= IDS_CERT_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION
;
232 case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION
:
233 string_id
= IDS_CERT_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION
;
235 case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION
:
236 string_id
= IDS_CERT_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION
;
238 case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION
:
239 string_id
= IDS_CERT_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION
;
241 case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION
:
242 string_id
= IDS_CERT_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION
;
244 case SEC_OID_NS_CERT_EXT_CERT_TYPE
:
245 string_id
= IDS_CERT_EXT_NS_CERT_TYPE
;
247 case SEC_OID_NS_CERT_EXT_BASE_URL
:
248 string_id
= IDS_CERT_EXT_NS_CERT_BASE_URL
;
250 case SEC_OID_NS_CERT_EXT_REVOCATION_URL
:
251 string_id
= IDS_CERT_EXT_NS_CERT_REVOCATION_URL
;
253 case SEC_OID_NS_CERT_EXT_CA_REVOCATION_URL
:
254 string_id
= IDS_CERT_EXT_NS_CA_REVOCATION_URL
;
256 case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_URL
:
257 string_id
= IDS_CERT_EXT_NS_CERT_RENEWAL_URL
;
259 case SEC_OID_NS_CERT_EXT_CA_POLICY_URL
:
260 string_id
= IDS_CERT_EXT_NS_CA_POLICY_URL
;
262 case SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME
:
263 string_id
= IDS_CERT_EXT_NS_SSL_SERVER_NAME
;
265 case SEC_OID_NS_CERT_EXT_COMMENT
:
266 string_id
= IDS_CERT_EXT_NS_COMMENT
;
268 case SEC_OID_NS_CERT_EXT_LOST_PASSWORD_URL
:
269 string_id
= IDS_CERT_EXT_NS_LOST_PASSWORD_URL
;
271 case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_TIME
:
272 string_id
= IDS_CERT_EXT_NS_CERT_RENEWAL_TIME
;
274 case SEC_OID_X509_SUBJECT_DIRECTORY_ATTR
:
275 string_id
= IDS_CERT_X509_SUBJECT_DIRECTORY_ATTR
;
277 case SEC_OID_X509_SUBJECT_KEY_ID
:
278 string_id
= IDS_CERT_X509_SUBJECT_KEYID
;
280 case SEC_OID_X509_KEY_USAGE
:
281 string_id
= IDS_CERT_X509_KEY_USAGE
;
283 case SEC_OID_X509_SUBJECT_ALT_NAME
:
284 string_id
= IDS_CERT_X509_SUBJECT_ALT_NAME
;
286 case SEC_OID_X509_ISSUER_ALT_NAME
:
287 string_id
= IDS_CERT_X509_ISSUER_ALT_NAME
;
289 case SEC_OID_X509_BASIC_CONSTRAINTS
:
290 string_id
= IDS_CERT_X509_BASIC_CONSTRAINTS
;
292 case SEC_OID_X509_NAME_CONSTRAINTS
:
293 string_id
= IDS_CERT_X509_NAME_CONSTRAINTS
;
295 case SEC_OID_X509_CRL_DIST_POINTS
:
296 string_id
= IDS_CERT_X509_CRL_DIST_POINTS
;
298 case SEC_OID_X509_CERTIFICATE_POLICIES
:
299 string_id
= IDS_CERT_X509_CERT_POLICIES
;
301 case SEC_OID_X509_POLICY_MAPPINGS
:
302 string_id
= IDS_CERT_X509_POLICY_MAPPINGS
;
304 case SEC_OID_X509_POLICY_CONSTRAINTS
:
305 string_id
= IDS_CERT_X509_POLICY_CONSTRAINTS
;
307 case SEC_OID_X509_AUTH_KEY_ID
:
308 string_id
= IDS_CERT_X509_AUTH_KEYID
;
310 case SEC_OID_X509_EXT_KEY_USAGE
:
311 string_id
= IDS_CERT_X509_EXT_KEY_USAGE
;
313 case SEC_OID_X509_AUTH_INFO_ACCESS
:
314 string_id
= IDS_CERT_X509_AUTH_INFO_ACCESS
;
316 case SEC_OID_EXT_KEY_USAGE_SERVER_AUTH
:
317 string_id
= IDS_CERT_EKU_TLS_WEB_SERVER_AUTHENTICATION
;
319 case SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH
:
320 string_id
= IDS_CERT_EKU_TLS_WEB_CLIENT_AUTHENTICATION
;
322 case SEC_OID_EXT_KEY_USAGE_CODE_SIGN
:
323 string_id
= IDS_CERT_EKU_CODE_SIGNING
;
325 case SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT
:
326 string_id
= IDS_CERT_EKU_EMAIL_PROTECTION
;
328 case SEC_OID_EXT_KEY_USAGE_TIME_STAMP
:
329 string_id
= IDS_CERT_EKU_TIME_STAMPING
;
331 case SEC_OID_OCSP_RESPONDER
:
332 string_id
= IDS_CERT_EKU_OCSP_SIGNING
;
334 case SEC_OID_PKIX_CPS_POINTER_QUALIFIER
:
335 string_id
= IDS_CERT_PKIX_CPS_POINTER_QUALIFIER
;
337 case SEC_OID_PKIX_USER_NOTICE_QUALIFIER
:
338 string_id
= IDS_CERT_PKIX_USER_NOTICE_QUALIFIER
;
340 case SEC_OID_UNKNOWN
:
344 // There are a billionty other OIDs we could add here. I tried to get the
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
;
394 return l10n_util::GetStringUTF8(string_id
);
396 return DumpOidString(oid
);
399 // Get a display string from a Relative Distinguished Name.
400 std::string
ProcessRDN(CERTRDN
* rdn
) {
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
);
408 // TODO(mattm): Pass decode_item to CERT_RFC1485_EscapeAndQuote.
410 std::string
value(reinterpret_cast<char*>(decode_item
->data
),
412 if (SECOID_FindOIDTag(&avas
[i
]->type
) == SEC_OID_AVA_COMMON_NAME
)
413 value
= x509_certificate_model::ProcessIDN(value
);
415 SECITEM_FreeItem(decode_item
, PR_TRUE
);
423 std::string
ProcessName(CERTName
* name
) {
427 // Find last non-NULL rdn.
428 for (last_rdn
= name
->rdns
; last_rdn
[0]; last_rdn
++) {}
431 for (CERTRDN
** rdn
= last_rdn
; rdn
>= name
->rdns
; rdn
--)
432 rv
+= ProcessRDN(*rdn
);
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
);
444 rv
= l10n_util::GetStringUTF8(IDS_CERT_X509_BASIC_CONSTRAINT_IS_CA
);
446 rv
= l10n_util::GetStringUTF8(IDS_CERT_X509_BASIC_CONSTRAINT_IS_NOT_CA
);
448 if (value
.pathLenConstraint
!= -1) {
449 base::string16 depth
;
450 if (value
.pathLenConstraint
== CERT_UNLIMITED_PATH_CONSTRAINT
) {
451 depth
= l10n_util::GetStringUTF16(
452 IDS_CERT_X509_BASIC_CONSTRAINT_PATH_LEN_UNLIMITED
);
454 depth
= base::FormatNumber(value
.pathLenConstraint
);
456 rv
+= l10n_util::GetStringFUTF8(IDS_CERT_X509_BASIC_CONSTRAINT_PATH_LEN
,
462 std::string
ProcessGeneralName(PRArenaPool
* arena
,
463 CERTGeneralName
* current
) {
469 switch (current
->type
) {
470 case certOtherName
: {
471 key
= GetOIDText(¤t
->name
.OthName
.oid
);
472 SECOidTag oid_tag
= SECOID_FindOIDTag(¤t
->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
479 if (SEC_ASN1DecodeItem(arena
, &decoded
,
480 SEC_ASN1_GET(SEC_UTF8StringTemplate
),
481 ¤t
->name
.OthName
.name
) == SECSuccess
) {
482 value
= std::string(reinterpret_cast<char*>(decoded
.data
),
485 value
= ProcessRawBytes(¤t
->name
.OthName
.name
);
488 } else if (oid_tag
== ms_ntds_replication
) {
489 // This should be a 16-byte GUID.
491 if (SEC_ASN1DecodeItem(arena
, &guid
,
492 SEC_ASN1_GET(SEC_OctetStringTemplate
),
493 ¤t
->name
.OthName
.name
) == SECSuccess
&&
495 unsigned char* d
= guid
.data
;
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]);
503 value
= ProcessRawBytes(¤t
->name
.OthName
.name
);
506 value
= ProcessRawBytes(¤t
->name
.OthName
.name
);
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
);
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
);
521 case certX400Address
:
522 key
= l10n_util::GetStringUTF8(IDS_CERT_GENERAL_NAME_X400_ADDRESS
);
523 value
= ProcessRawBytes(¤t
->name
.other
);
525 case certDirectoryName
:
526 key
= l10n_util::GetStringUTF8(IDS_CERT_GENERAL_NAME_DIRECTORY_NAME
);
527 value
= ProcessName(¤t
->name
.directoryName
);
529 case certEDIPartyName
:
530 key
= l10n_util::GetStringUTF8(IDS_CERT_GENERAL_NAME_EDI_PARTY_NAME
);
531 value
= ProcessRawBytes(¤t
->name
.other
);
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
);
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();
545 // Invalid IP address.
546 value
= ProcessRawBytes(¤t
->name
.other
);
551 key
= l10n_util::GetStringUTF8(IDS_CERT_GENERAL_NAME_REGISTERED_ID
);
552 value
= DumpOidString(¤t
->name
.other
);
555 std::string
rv(l10n_util::GetStringFUTF8(IDS_CERT_UNKNOWN_OID_INFO_FORMAT
,
556 base::UTF8ToUTF16(key
),
557 base::UTF8ToUTF16(value
)));
562 std::string
ProcessGeneralNames(PRArenaPool
* arena
,
563 CERTGeneralName
* name_list
) {
565 CERTGeneralName
* current
= name_list
;
568 std::string text
= ProcessGeneralName(arena
, current
);
572 current
= CERT_GetNextGeneralName(current
);
573 } while (current
!= name_list
);
577 std::string
ProcessAltName(SECItem
* extension_data
) {
578 CERTGeneralName
* name_list
;
580 crypto::ScopedPLArenaPool
arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE
));
583 name_list
= CERT_DecodeAltNameExtension(arena
.get(), extension_data
);
585 return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR
);
587 return ProcessGeneralNames(arena
.get(), name_list
);
590 std::string
ProcessSubjectKeyId(SECItem
* extension_data
) {
592 crypto::ScopedPLArenaPool
arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE
));
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
);
603 rv
= l10n_util::GetStringFUTF8(IDS_CERT_KEYID_FORMAT
,
604 base::ASCIIToUTF16(ProcessRawBytes(&decoded
)));
608 std::string
ProcessAuthKeyId(SECItem
* extension_data
) {
610 crypto::ScopedPLArenaPool
arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE
));
615 ret
= CERT_DecodeAuthKeyID(arena
.get(), extension_data
);
617 if (ret
->keyID
.len
> 0) {
618 rv
+= l10n_util::GetStringFUTF8(IDS_CERT_KEYID_FORMAT
,
620 ProcessRawBytes(&ret
->keyID
)));
624 if (ret
->authCertIssuer
) {
625 rv
+= l10n_util::GetStringFUTF8(
626 IDS_CERT_ISSUER_FORMAT
,
628 ProcessGeneralNames(arena
.get(), ret
->authCertIssuer
)));
632 if (ret
->authCertSerialNumber
.len
> 0) {
633 rv
+= l10n_util::GetStringFUTF8(
634 IDS_CERT_SERIAL_NUMBER_FORMAT
,
635 base::ASCIIToUTF16(ProcessRawBytes(&ret
->authCertSerialNumber
)));
642 std::string
ProcessUserNotice(SECItem
* der_notice
) {
643 CERTUserNotice
* notice
= CERT_DecodeUserNotice(der_notice
);
645 return ProcessRawBytes(der_notice
);
648 if (notice
->noticeReference
.organization
.len
!= 0) {
649 switch (notice
->noticeReference
.organization
.type
) {
651 case siVisibleString
:
654 reinterpret_cast<char*>(notice
->noticeReference
.organization
.data
),
655 notice
->noticeReference
.organization
.len
);
658 rv
+= ProcessBMPString(¬ice
->noticeReference
.organization
);
664 SECItem
** itemList
= notice
->noticeReference
.noticeNumbers
;
666 unsigned long number
;
667 if (SEC_ASN1DecodeInteger(*itemList
, &number
) == SECSuccess
) {
668 if (itemList
!= notice
->noticeReference
.noticeNumbers
)
671 rv
+= base::UTF16ToUTF8(base::UintToString16(number
));
676 if (notice
->displayText
.len
!= 0) {
678 switch (notice
->displayText
.type
) {
680 case siVisibleString
:
682 rv
+= std::string(reinterpret_cast<char*>(notice
->displayText
.data
),
683 notice
->displayText
.len
);
686 rv
+= ProcessBMPString(¬ice
->displayText
);
693 CERT_DestroyUserNotice(notice
);
697 std::string
ProcessCertificatePolicies(SECItem
* extension_data
) {
700 CERTCertificatePolicies
* policies
= CERT_DecodeCertificatePoliciesExtension(
703 return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR
);
705 CERTPolicyInfo
** policyInfos
= policies
->policyInfos
;
706 while (*policyInfos
) {
707 CERTPolicyInfo
* policyInfo
= *policyInfos
++;
708 std::string key
= GetOIDText(&policyInfo
->policyID
);
710 // If we have policy qualifiers, display the oid text
711 // with a ':', otherwise just put the oid text and a newline.
712 // TODO(mattm): Add extra note if this is the ev oid? (It's a bit
713 // complicated, since we don't want to do the EV check synchronously.)
714 if (policyInfo
->policyQualifiers
) {
715 rv
+= l10n_util::GetStringFUTF8(IDS_CERT_MULTILINE_INFO_START_FORMAT
,
716 base::UTF8ToUTF16(key
));
722 if (policyInfo
->policyQualifiers
) {
723 // Add all qualifiers on separate lines, indented.
724 CERTPolicyQualifier
** policyQualifiers
= policyInfo
->policyQualifiers
;
725 while (*policyQualifiers
!= NULL
) {
728 CERTPolicyQualifier
* policyQualifier
= *policyQualifiers
++;
729 rv
+= l10n_util::GetStringFUTF8(
730 IDS_CERT_MULTILINE_INFO_START_FORMAT
,
731 base::UTF8ToUTF16(GetOIDText(&policyQualifier
->qualifierID
)));
732 switch(policyQualifier
->oid
) {
733 case SEC_OID_PKIX_CPS_POINTER_QUALIFIER
:
735 /* The CPS pointer ought to be the cPSuri alternative
736 of the Qualifier choice. */
737 rv
+= ProcessIA5String(&policyQualifier
->qualifierValue
);
739 case SEC_OID_PKIX_USER_NOTICE_QUALIFIER
:
740 rv
+= ProcessUserNotice(&policyQualifier
->qualifierValue
);
743 rv
+= ProcessRawBytes(&policyQualifier
->qualifierValue
);
751 CERT_DestroyCertificatePoliciesExtension(policies
);
755 std::string
ProcessCrlDistPoints(SECItem
* extension_data
) {
757 CERTCrlDistributionPoints
* crldp
;
758 CRLDistributionPoint
** points
;
759 CRLDistributionPoint
* point
;
762 static const struct {
765 } reason_string_map
[] = {
766 {RF_UNUSED
, IDS_CERT_REVOCATION_REASON_UNUSED
},
767 {RF_KEY_COMPROMISE
, IDS_CERT_REVOCATION_REASON_KEY_COMPROMISE
},
768 {RF_CA_COMPROMISE
, IDS_CERT_REVOCATION_REASON_CA_COMPROMISE
},
769 {RF_AFFILIATION_CHANGED
, IDS_CERT_REVOCATION_REASON_AFFILIATION_CHANGED
},
770 {RF_SUPERSEDED
, IDS_CERT_REVOCATION_REASON_SUPERSEDED
},
771 {RF_CESSATION_OF_OPERATION
,
772 IDS_CERT_REVOCATION_REASON_CESSATION_OF_OPERATION
},
773 {RF_CERTIFICATE_HOLD
, IDS_CERT_REVOCATION_REASON_CERTIFICATE_HOLD
},
776 crypto::ScopedPLArenaPool
arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE
));
779 crldp
= CERT_DecodeCRLDistributionPoints(arena
.get(), extension_data
);
780 if (!crldp
|| !crldp
->distPoints
) {
781 rv
= l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR
);
785 for (points
= crldp
->distPoints
; *points
; ++points
) {
787 switch (point
->distPointType
) {
789 // generalName is a typo in upstream NSS; fullName is actually a
790 // GeneralNames (SEQUENCE OF GeneralName). See Mozilla Bug #615100.
791 rv
+= ProcessGeneralNames(arena
.get(), point
->distPoint
.fullName
);
793 case relativeDistinguishedName
:
794 rv
+= ProcessRDN(&point
->distPoint
.relativeName
);
797 if (point
->reasons
.len
) {
800 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(reason_string_map
); ++i
) {
801 if (point
->reasons
.data
[0] & reason_string_map
[i
].reason
) {
804 rv
+= l10n_util::GetStringUTF8(reason_string_map
[i
].string_id
);
810 if (point
->crlIssuer
) {
811 rv
+= l10n_util::GetStringFUTF8(
812 IDS_CERT_ISSUER_FORMAT
,
814 ProcessGeneralNames(arena
.get(), point
->crlIssuer
)));
820 std::string
ProcessAuthInfoAccess(SECItem
* extension_data
) {
822 CERTAuthInfoAccess
** aia
;
823 CERTAuthInfoAccess
* desc
;
824 crypto::ScopedPLArenaPool
arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE
));
827 aia
= CERT_DecodeAuthInfoAccessExtension(arena
.get(), extension_data
);
829 return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR
);
831 while (*aia
!= NULL
) {
833 base::string16 location_str
=
834 base::UTF8ToUTF16(ProcessGeneralName(arena
.get(), desc
->location
));
835 switch (SECOID_FindOIDTag(&desc
->method
)) {
836 case SEC_OID_PKIX_OCSP
:
837 rv
+= l10n_util::GetStringFUTF8(IDS_CERT_OCSP_RESPONDER_FORMAT
,
840 case SEC_OID_PKIX_CA_ISSUERS
:
841 rv
+= l10n_util::GetStringFUTF8(IDS_CERT_CA_ISSUERS_FORMAT
,
845 rv
+= l10n_util::GetStringFUTF8(IDS_CERT_UNKNOWN_OID_INFO_FORMAT
,
847 GetOIDText(&desc
->method
)),
855 std::string
ProcessIA5String(SECItem
* extension_data
) {
857 if (SEC_ASN1DecodeItem(NULL
, &item
, SEC_ASN1_GET(SEC_IA5StringTemplate
),
858 extension_data
) != SECSuccess
)
859 return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR
);
860 std::string
rv((char*)item
.data
, item
.len
); // ASCII data.
861 PORT_Free(item
.data
);
865 std::string
ProcessBMPString(SECItem
* extension_data
) {
868 crypto::ScopedPLArenaPool
arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE
));
871 if (SEC_ASN1DecodeItem(arena
.get(), &item
,
872 SEC_ASN1_GET(SEC_BMPStringTemplate
), extension_data
) ==
874 rv
= BMPtoUTF8(arena
.get(), item
.data
, item
.len
);
883 static std::string
ProcessBitField(SECItem
* bitfield
,
884 const MaskIdPair
* string_map
,
887 unsigned int bits
= 0;
889 for (size_t i
= 0; i
* 8 < bitfield
->len
&& i
< sizeof(bits
); ++i
)
890 bits
|= bitfield
->data
[i
] << (i
* 8);
891 for (size_t i
= 0; i
< len
; ++i
) {
892 if (bits
& string_map
[i
].mask
) {
895 rv
+= l10n_util::GetStringUTF8(string_map
[i
].string_id
);
901 static std::string
ProcessBitStringExtension(SECItem
* extension_data
,
902 const MaskIdPair
* string_map
,
906 decoded
.type
= siBuffer
;
909 if (SEC_ASN1DecodeItem(NULL
, &decoded
, SEC_ASN1_GET(SEC_BitStringTemplate
),
910 extension_data
) != SECSuccess
)
911 return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR
);
912 std::string rv
= ProcessBitField(&decoded
, string_map
, len
, separator
);
913 PORT_Free(decoded
.data
);
917 std::string
ProcessNSCertTypeExtension(SECItem
* extension_data
) {
918 static const MaskIdPair usage_string_map
[] = {
919 {NS_CERT_TYPE_SSL_CLIENT
, IDS_CERT_USAGE_SSL_CLIENT
},
920 {NS_CERT_TYPE_SSL_SERVER
, IDS_CERT_USAGE_SSL_SERVER
},
921 {NS_CERT_TYPE_EMAIL
, IDS_CERT_EXT_NS_CERT_TYPE_EMAIL
},
922 {NS_CERT_TYPE_OBJECT_SIGNING
, IDS_CERT_USAGE_OBJECT_SIGNER
},
923 {NS_CERT_TYPE_SSL_CA
, IDS_CERT_USAGE_SSL_CA
},
924 {NS_CERT_TYPE_EMAIL_CA
, IDS_CERT_EXT_NS_CERT_TYPE_EMAIL_CA
},
925 {NS_CERT_TYPE_OBJECT_SIGNING_CA
, IDS_CERT_USAGE_OBJECT_SIGNER
},
927 return ProcessBitStringExtension(extension_data
, usage_string_map
,
928 ARRAYSIZE_UNSAFE(usage_string_map
), '\n');
931 static const MaskIdPair key_usage_string_map
[] = {
932 {KU_DIGITAL_SIGNATURE
, IDS_CERT_X509_KEY_USAGE_SIGNING
},
933 {KU_NON_REPUDIATION
, IDS_CERT_X509_KEY_USAGE_NONREP
},
934 {KU_KEY_ENCIPHERMENT
, IDS_CERT_X509_KEY_USAGE_ENCIPHERMENT
},
935 {KU_DATA_ENCIPHERMENT
, IDS_CERT_X509_KEY_USAGE_DATA_ENCIPHERMENT
},
936 {KU_KEY_AGREEMENT
, IDS_CERT_X509_KEY_USAGE_KEY_AGREEMENT
},
937 {KU_KEY_CERT_SIGN
, IDS_CERT_X509_KEY_USAGE_CERT_SIGNER
},
938 {KU_CRL_SIGN
, IDS_CERT_X509_KEY_USAGE_CRL_SIGNER
},
939 {KU_ENCIPHER_ONLY
, IDS_CERT_X509_KEY_USAGE_ENCIPHER_ONLY
},
940 // NSS is missing a flag for dechiperOnly, see:
941 // https://bugzilla.mozilla.org/show_bug.cgi?id=549952
944 std::string
ProcessKeyUsageBitString(SECItem
* bitstring
, char sep
) {
945 return ProcessBitField(bitstring
, key_usage_string_map
,
946 arraysize(key_usage_string_map
), sep
);
949 std::string
ProcessKeyUsageExtension(SECItem
* extension_data
) {
950 return ProcessBitStringExtension(extension_data
, key_usage_string_map
,
951 arraysize(key_usage_string_map
), '\n');
954 std::string
ProcessExtKeyUsage(SECItem
* extension_data
) {
956 CERTOidSequence
* extension_key_usage
= NULL
;
957 extension_key_usage
= CERT_DecodeOidSequence(extension_data
);
958 if (extension_key_usage
== NULL
)
959 return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR
);
963 for (oids
= extension_key_usage
->oids
; oids
!= NULL
&& *oids
!= NULL
;
966 std::string oid_dump
= DumpOidString(oid
);
967 std::string oid_text
= GetOIDText(oid
);
969 // If oid is one we recognize, oid_text will have a text description of the
970 // OID, which we display along with the oid_dump. If we don't recognize the
971 // OID, GetOIDText will return the same value as DumpOidString, so just
972 // display the OID alone.
973 if (oid_dump
== oid_text
)
976 rv
+= l10n_util::GetStringFUTF8(IDS_CERT_EXT_KEY_USAGE_FORMAT
,
977 base::UTF8ToUTF16(oid_text
),
978 base::UTF8ToUTF16(oid_dump
));
981 CERT_DestroyOidSequence(extension_key_usage
);
985 std::string
ProcessExtensionData(SECOidTag oid_tag
, SECItem
* extension_data
) {
986 // This (and its sub-functions) are based on the same-named functions in
987 // security/manager/ssl/src/nsNSSCertHelper.cpp.
989 case SEC_OID_NS_CERT_EXT_CERT_TYPE
:
990 return ProcessNSCertTypeExtension(extension_data
);
991 case SEC_OID_X509_KEY_USAGE
:
992 return ProcessKeyUsageExtension(extension_data
);
993 case SEC_OID_X509_BASIC_CONSTRAINTS
:
994 return ProcessBasicConstraints(extension_data
);
995 case SEC_OID_X509_EXT_KEY_USAGE
:
996 return ProcessExtKeyUsage(extension_data
);
997 case SEC_OID_X509_ISSUER_ALT_NAME
:
998 case SEC_OID_X509_SUBJECT_ALT_NAME
:
999 return ProcessAltName(extension_data
);
1000 case SEC_OID_X509_SUBJECT_KEY_ID
:
1001 return ProcessSubjectKeyId(extension_data
);
1002 case SEC_OID_X509_AUTH_KEY_ID
:
1003 return ProcessAuthKeyId(extension_data
);
1004 case SEC_OID_X509_CERTIFICATE_POLICIES
:
1005 return ProcessCertificatePolicies(extension_data
);
1006 case SEC_OID_X509_CRL_DIST_POINTS
:
1007 return ProcessCrlDistPoints(extension_data
);
1008 case SEC_OID_X509_AUTH_INFO_ACCESS
:
1009 return ProcessAuthInfoAccess(extension_data
);
1010 case SEC_OID_NS_CERT_EXT_BASE_URL
:
1011 case SEC_OID_NS_CERT_EXT_REVOCATION_URL
:
1012 case SEC_OID_NS_CERT_EXT_CA_REVOCATION_URL
:
1013 case SEC_OID_NS_CERT_EXT_CA_CERT_URL
:
1014 case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_URL
:
1015 case SEC_OID_NS_CERT_EXT_CA_POLICY_URL
:
1016 case SEC_OID_NS_CERT_EXT_HOMEPAGE_URL
:
1017 case SEC_OID_NS_CERT_EXT_COMMENT
:
1018 case SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME
:
1019 case SEC_OID_NS_CERT_EXT_LOST_PASSWORD_URL
:
1020 return ProcessIA5String(extension_data
);
1022 if (oid_tag
== ms_cert_ext_certtype
)
1023 return ProcessBMPString(extension_data
);
1024 return ProcessRawBytes(extension_data
);
1028 std::string
ProcessSubjectPublicKeyInfo(CERTSubjectPublicKeyInfo
* spki
) {
1030 SECKEYPublicKey
* key
= SECKEY_ExtractPublicKey(spki
);
1032 switch (key
->keyType
) {
1034 rv
= l10n_util::GetStringFUTF8(
1035 IDS_CERT_RSA_PUBLIC_KEY_DUMP_FORMAT
,
1036 base::UintToString16(key
->u
.rsa
.modulus
.len
* 8),
1037 base::UTF8ToUTF16(ProcessRawBytes(&key
->u
.rsa
.modulus
)),
1038 base::UintToString16(key
->u
.rsa
.publicExponent
.len
* 8),
1039 base::UTF8ToUTF16(ProcessRawBytes(&key
->u
.rsa
.publicExponent
)));
1043 rv
= x509_certificate_model::ProcessRawBits(
1044 spki
->subjectPublicKey
.data
, spki
->subjectPublicKey
.len
);
1047 SECKEY_DestroyPublicKey(key
);
1052 net::CertType
GetCertType(CERTCertificate
*cert
) {
1053 CERTCertTrust trust
= {0};
1054 CERT_GetCertTrust(cert
, &trust
);
1056 unsigned all_flags
= trust
.sslFlags
| trust
.emailFlags
|
1057 trust
.objectSigningFlags
;
1059 if (cert
->nickname
&& (all_flags
& CERTDB_USER
))
1060 return net::USER_CERT
;
1061 if ((all_flags
& CERTDB_VALID_CA
) || CERT_IsCACert(cert
, NULL
))
1062 return net::CA_CERT
;
1063 // TODO(mattm): http://crbug.com/128633.
1064 if (trust
.sslFlags
& CERTDB_TERMINAL_RECORD
)
1065 return net::SERVER_CERT
;
1066 return net::OTHER_CERT
;
1069 } // namespace mozilla_security_manager