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) {
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
,
557 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 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
,
619 ASCIIToUTF16(ProcessRawBytes(&ret
->keyID
)));
623 if (ret
->authCertIssuer
) {
624 rv
+= l10n_util::GetStringFUTF8(
625 IDS_CERT_ISSUER_FORMAT
,
626 UTF8ToUTF16(ProcessGeneralNames(arena
.get(), ret
->authCertIssuer
)));
630 if (ret
->authCertSerialNumber
.len
> 0) {
631 rv
+= l10n_util::GetStringFUTF8(
632 IDS_CERT_SERIAL_NUMBER_FORMAT
,
633 ASCIIToUTF16(ProcessRawBytes(&ret
->authCertSerialNumber
)));
640 std::string
ProcessUserNotice(SECItem
* der_notice
) {
641 CERTUserNotice
* notice
= CERT_DecodeUserNotice(der_notice
);
643 return ProcessRawBytes(der_notice
);
646 if (notice
->noticeReference
.organization
.len
!= 0) {
647 switch (notice
->noticeReference
.organization
.type
) {
649 case siVisibleString
:
652 reinterpret_cast<char*>(notice
->noticeReference
.organization
.data
),
653 notice
->noticeReference
.organization
.len
);
656 rv
+= ProcessBMPString(¬ice
->noticeReference
.organization
);
662 SECItem
** itemList
= notice
->noticeReference
.noticeNumbers
;
664 unsigned long number
;
665 if (SEC_ASN1DecodeInteger(*itemList
, &number
) == SECSuccess
) {
666 if (itemList
!= notice
->noticeReference
.noticeNumbers
)
669 rv
+= UTF16ToUTF8(base::UintToString16(number
));
674 if (notice
->displayText
.len
!= 0) {
676 switch (notice
->displayText
.type
) {
678 case siVisibleString
:
680 rv
+= std::string(reinterpret_cast<char*>(notice
->displayText
.data
),
681 notice
->displayText
.len
);
684 rv
+= ProcessBMPString(¬ice
->displayText
);
691 CERT_DestroyUserNotice(notice
);
695 std::string
ProcessCertificatePolicies(SECItem
* extension_data
) {
698 CERTCertificatePolicies
* policies
= CERT_DecodeCertificatePoliciesExtension(
701 return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR
);
703 CERTPolicyInfo
** policyInfos
= policies
->policyInfos
;
704 while (*policyInfos
) {
705 CERTPolicyInfo
* policyInfo
= *policyInfos
++;
706 std::string key
= GetOIDText(&policyInfo
->policyID
);
708 // If we have policy qualifiers, display the oid text
709 // with a ':', otherwise just put the oid text and a newline.
710 // TODO(mattm): Add extra note if this is the ev oid? (It's a bit
711 // complicated, since we don't want to do the EV check synchronously.)
712 if (policyInfo
->policyQualifiers
) {
713 rv
+= l10n_util::GetStringFUTF8(IDS_CERT_MULTILINE_INFO_START_FORMAT
,
720 if (policyInfo
->policyQualifiers
) {
721 // Add all qualifiers on separate lines, indented.
722 CERTPolicyQualifier
** policyQualifiers
= policyInfo
->policyQualifiers
;
723 while (*policyQualifiers
!= NULL
) {
726 CERTPolicyQualifier
* policyQualifier
= *policyQualifiers
++;
727 rv
+= l10n_util::GetStringFUTF8(
728 IDS_CERT_MULTILINE_INFO_START_FORMAT
,
729 UTF8ToUTF16(GetOIDText(&policyQualifier
->qualifierID
)));
730 switch(policyQualifier
->oid
) {
731 case SEC_OID_PKIX_CPS_POINTER_QUALIFIER
:
733 /* The CPS pointer ought to be the cPSuri alternative
734 of the Qualifier choice. */
735 rv
+= ProcessIA5String(&policyQualifier
->qualifierValue
);
737 case SEC_OID_PKIX_USER_NOTICE_QUALIFIER
:
738 rv
+= ProcessUserNotice(&policyQualifier
->qualifierValue
);
741 rv
+= ProcessRawBytes(&policyQualifier
->qualifierValue
);
749 CERT_DestroyCertificatePoliciesExtension(policies
);
753 std::string
ProcessCrlDistPoints(SECItem
* extension_data
) {
755 CERTCrlDistributionPoints
* crldp
;
756 CRLDistributionPoint
** points
;
757 CRLDistributionPoint
* point
;
760 static const struct {
763 } reason_string_map
[] = {
764 {RF_UNUSED
, IDS_CERT_REVOCATION_REASON_UNUSED
},
765 {RF_KEY_COMPROMISE
, IDS_CERT_REVOCATION_REASON_KEY_COMPROMISE
},
766 {RF_CA_COMPROMISE
, IDS_CERT_REVOCATION_REASON_CA_COMPROMISE
},
767 {RF_AFFILIATION_CHANGED
, IDS_CERT_REVOCATION_REASON_AFFILIATION_CHANGED
},
768 {RF_SUPERSEDED
, IDS_CERT_REVOCATION_REASON_SUPERSEDED
},
769 {RF_CESSATION_OF_OPERATION
,
770 IDS_CERT_REVOCATION_REASON_CESSATION_OF_OPERATION
},
771 {RF_CERTIFICATE_HOLD
, IDS_CERT_REVOCATION_REASON_CERTIFICATE_HOLD
},
774 crypto::ScopedPLArenaPool
arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE
));
777 crldp
= CERT_DecodeCRLDistributionPoints(arena
.get(), extension_data
);
778 if (!crldp
|| !crldp
->distPoints
) {
779 rv
= l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR
);
783 for (points
= crldp
->distPoints
; *points
; ++points
) {
785 switch (point
->distPointType
) {
787 // generalName is a typo in upstream NSS; fullName is actually a
788 // GeneralNames (SEQUENCE OF GeneralName). See Mozilla Bug #615100.
789 rv
+= ProcessGeneralNames(arena
.get(), point
->distPoint
.fullName
);
791 case relativeDistinguishedName
:
792 rv
+= ProcessRDN(&point
->distPoint
.relativeName
);
795 if (point
->reasons
.len
) {
798 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(reason_string_map
); ++i
) {
799 if (point
->reasons
.data
[0] & reason_string_map
[i
].reason
) {
802 rv
+= l10n_util::GetStringUTF8(reason_string_map
[i
].string_id
);
808 if (point
->crlIssuer
) {
809 rv
+= l10n_util::GetStringFUTF8(
810 IDS_CERT_ISSUER_FORMAT
,
811 UTF8ToUTF16(ProcessGeneralNames(arena
.get(), point
->crlIssuer
)));
817 std::string
ProcessAuthInfoAccess(SECItem
* extension_data
) {
819 CERTAuthInfoAccess
** aia
;
820 CERTAuthInfoAccess
* desc
;
821 crypto::ScopedPLArenaPool
arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE
));
824 aia
= CERT_DecodeAuthInfoAccessExtension(arena
.get(), extension_data
);
826 return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR
);
828 while (*aia
!= NULL
) {
830 string16 location_str
= UTF8ToUTF16(ProcessGeneralName(arena
.get(),
832 switch (SECOID_FindOIDTag(&desc
->method
)) {
833 case SEC_OID_PKIX_OCSP
:
834 rv
+= l10n_util::GetStringFUTF8(IDS_CERT_OCSP_RESPONDER_FORMAT
,
837 case SEC_OID_PKIX_CA_ISSUERS
:
838 rv
+= l10n_util::GetStringFUTF8(IDS_CERT_CA_ISSUERS_FORMAT
,
842 rv
+= l10n_util::GetStringFUTF8(IDS_CERT_UNKNOWN_OID_INFO_FORMAT
,
843 UTF8ToUTF16(GetOIDText(&desc
->method
)),
851 std::string
ProcessIA5String(SECItem
* extension_data
) {
853 if (SEC_ASN1DecodeItem(NULL
, &item
, SEC_ASN1_GET(SEC_IA5StringTemplate
),
854 extension_data
) != SECSuccess
)
855 return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR
);
856 std::string
rv((char*)item
.data
, item
.len
); // ASCII data.
857 PORT_Free(item
.data
);
861 std::string
ProcessBMPString(SECItem
* extension_data
) {
864 crypto::ScopedPLArenaPool
arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE
));
867 if (SEC_ASN1DecodeItem(arena
.get(), &item
,
868 SEC_ASN1_GET(SEC_BMPStringTemplate
), extension_data
) ==
870 rv
= BMPtoUTF8(arena
.get(), item
.data
, item
.len
);
879 static std::string
ProcessBitField(SECItem
* bitfield
,
880 const MaskIdPair
* string_map
,
883 unsigned int bits
= 0;
885 for (size_t i
= 0; i
* 8 < bitfield
->len
&& i
< sizeof(bits
); ++i
)
886 bits
|= bitfield
->data
[i
] << (i
* 8);
887 for (size_t i
= 0; i
< len
; ++i
) {
888 if (bits
& string_map
[i
].mask
) {
891 rv
+= l10n_util::GetStringUTF8(string_map
[i
].string_id
);
897 static std::string
ProcessBitStringExtension(SECItem
* extension_data
,
898 const MaskIdPair
* string_map
,
902 decoded
.type
= siBuffer
;
905 if (SEC_ASN1DecodeItem(NULL
, &decoded
, SEC_ASN1_GET(SEC_BitStringTemplate
),
906 extension_data
) != SECSuccess
)
907 return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR
);
908 std::string rv
= ProcessBitField(&decoded
, string_map
, len
, separator
);
909 PORT_Free(decoded
.data
);
913 std::string
ProcessNSCertTypeExtension(SECItem
* extension_data
) {
914 static const MaskIdPair usage_string_map
[] = {
915 {NS_CERT_TYPE_SSL_CLIENT
, IDS_CERT_USAGE_SSL_CLIENT
},
916 {NS_CERT_TYPE_SSL_SERVER
, IDS_CERT_USAGE_SSL_SERVER
},
917 {NS_CERT_TYPE_EMAIL
, IDS_CERT_EXT_NS_CERT_TYPE_EMAIL
},
918 {NS_CERT_TYPE_OBJECT_SIGNING
, IDS_CERT_USAGE_OBJECT_SIGNER
},
919 {NS_CERT_TYPE_SSL_CA
, IDS_CERT_USAGE_SSL_CA
},
920 {NS_CERT_TYPE_EMAIL_CA
, IDS_CERT_EXT_NS_CERT_TYPE_EMAIL_CA
},
921 {NS_CERT_TYPE_OBJECT_SIGNING_CA
, IDS_CERT_USAGE_OBJECT_SIGNER
},
923 return ProcessBitStringExtension(extension_data
, usage_string_map
,
924 ARRAYSIZE_UNSAFE(usage_string_map
), '\n');
927 static const MaskIdPair key_usage_string_map
[] = {
928 {KU_DIGITAL_SIGNATURE
, IDS_CERT_X509_KEY_USAGE_SIGNING
},
929 {KU_NON_REPUDIATION
, IDS_CERT_X509_KEY_USAGE_NONREP
},
930 {KU_KEY_ENCIPHERMENT
, IDS_CERT_X509_KEY_USAGE_ENCIPHERMENT
},
931 {KU_DATA_ENCIPHERMENT
, IDS_CERT_X509_KEY_USAGE_DATA_ENCIPHERMENT
},
932 {KU_KEY_AGREEMENT
, IDS_CERT_X509_KEY_USAGE_KEY_AGREEMENT
},
933 {KU_KEY_CERT_SIGN
, IDS_CERT_X509_KEY_USAGE_CERT_SIGNER
},
934 {KU_CRL_SIGN
, IDS_CERT_X509_KEY_USAGE_CRL_SIGNER
},
935 {KU_ENCIPHER_ONLY
, IDS_CERT_X509_KEY_USAGE_ENCIPHER_ONLY
},
936 // NSS is missing a flag for dechiperOnly, see:
937 // https://bugzilla.mozilla.org/show_bug.cgi?id=549952
940 std::string
ProcessKeyUsageBitString(SECItem
* bitstring
, char sep
) {
941 return ProcessBitField(bitstring
, key_usage_string_map
,
942 arraysize(key_usage_string_map
), sep
);
945 std::string
ProcessKeyUsageExtension(SECItem
* extension_data
) {
946 return ProcessBitStringExtension(extension_data
, key_usage_string_map
,
947 arraysize(key_usage_string_map
), '\n');
950 std::string
ProcessExtKeyUsage(SECItem
* extension_data
) {
952 CERTOidSequence
* extension_key_usage
= NULL
;
953 extension_key_usage
= CERT_DecodeOidSequence(extension_data
);
954 if (extension_key_usage
== NULL
)
955 return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR
);
959 for (oids
= extension_key_usage
->oids
; oids
!= NULL
&& *oids
!= NULL
;
962 std::string oid_dump
= DumpOidString(oid
);
963 std::string oid_text
= GetOIDText(oid
);
965 // If oid is one we recognize, oid_text will have a text description of the OID,
966 // which we display along with the oid_dump. If we don't recognize the OID,
967 // GetOIDText will return the same value as DumpOidString, so just display
969 if (oid_dump
== oid_text
)
972 rv
+= l10n_util::GetStringFUTF8(IDS_CERT_EXT_KEY_USAGE_FORMAT
,
973 UTF8ToUTF16(oid_text
),
974 UTF8ToUTF16(oid_dump
));
977 CERT_DestroyOidSequence(extension_key_usage
);
981 std::string
ProcessExtensionData(SECOidTag oid_tag
, SECItem
* extension_data
) {
982 // This (and its sub-functions) are based on the same-named functions in
983 // security/manager/ssl/src/nsNSSCertHelper.cpp.
985 case SEC_OID_NS_CERT_EXT_CERT_TYPE
:
986 return ProcessNSCertTypeExtension(extension_data
);
987 case SEC_OID_X509_KEY_USAGE
:
988 return ProcessKeyUsageExtension(extension_data
);
989 case SEC_OID_X509_BASIC_CONSTRAINTS
:
990 return ProcessBasicConstraints(extension_data
);
991 case SEC_OID_X509_EXT_KEY_USAGE
:
992 return ProcessExtKeyUsage(extension_data
);
993 case SEC_OID_X509_ISSUER_ALT_NAME
:
994 case SEC_OID_X509_SUBJECT_ALT_NAME
:
995 return ProcessAltName(extension_data
);
996 case SEC_OID_X509_SUBJECT_KEY_ID
:
997 return ProcessSubjectKeyId(extension_data
);
998 case SEC_OID_X509_AUTH_KEY_ID
:
999 return ProcessAuthKeyId(extension_data
);
1000 case SEC_OID_X509_CERTIFICATE_POLICIES
:
1001 return ProcessCertificatePolicies(extension_data
);
1002 case SEC_OID_X509_CRL_DIST_POINTS
:
1003 return ProcessCrlDistPoints(extension_data
);
1004 case SEC_OID_X509_AUTH_INFO_ACCESS
:
1005 return ProcessAuthInfoAccess(extension_data
);
1006 case SEC_OID_NS_CERT_EXT_BASE_URL
:
1007 case SEC_OID_NS_CERT_EXT_REVOCATION_URL
:
1008 case SEC_OID_NS_CERT_EXT_CA_REVOCATION_URL
:
1009 case SEC_OID_NS_CERT_EXT_CA_CERT_URL
:
1010 case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_URL
:
1011 case SEC_OID_NS_CERT_EXT_CA_POLICY_URL
:
1012 case SEC_OID_NS_CERT_EXT_HOMEPAGE_URL
:
1013 case SEC_OID_NS_CERT_EXT_COMMENT
:
1014 case SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME
:
1015 case SEC_OID_NS_CERT_EXT_LOST_PASSWORD_URL
:
1016 return ProcessIA5String(extension_data
);
1018 if (oid_tag
== ms_cert_ext_certtype
)
1019 return ProcessBMPString(extension_data
);
1020 return ProcessRawBytes(extension_data
);
1024 std::string
ProcessSubjectPublicKeyInfo(CERTSubjectPublicKeyInfo
* spki
) {
1026 SECKEYPublicKey
* key
= SECKEY_ExtractPublicKey(spki
);
1028 switch (key
->keyType
) {
1030 rv
= l10n_util::GetStringFUTF8(
1031 IDS_CERT_RSA_PUBLIC_KEY_DUMP_FORMAT
,
1032 base::UintToString16(key
->u
.rsa
.modulus
.len
* 8),
1033 UTF8ToUTF16(ProcessRawBytes(&key
->u
.rsa
.modulus
)),
1034 base::UintToString16(key
->u
.rsa
.publicExponent
.len
* 8),
1035 UTF8ToUTF16(ProcessRawBytes(&key
->u
.rsa
.publicExponent
)));
1039 rv
= x509_certificate_model::ProcessRawBits(
1040 spki
->subjectPublicKey
.data
, spki
->subjectPublicKey
.len
);
1043 SECKEY_DestroyPublicKey(key
);
1048 net::CertType
GetCertType(CERTCertificate
*cert
) {
1049 CERTCertTrust trust
= {0};
1050 CERT_GetCertTrust(cert
, &trust
);
1052 unsigned all_flags
= trust
.sslFlags
| trust
.emailFlags
|
1053 trust
.objectSigningFlags
;
1055 if (cert
->nickname
&& (all_flags
& CERTDB_USER
))
1056 return net::USER_CERT
;
1057 if ((all_flags
& CERTDB_VALID_CA
) || CERT_IsCACert(cert
, NULL
))
1058 return net::CA_CERT
;
1059 // TODO(mattm): http://crbug.com/128633.
1060 if (trust
.sslFlags
& CERTDB_TERMINAL_RECORD
)
1061 return net::SERVER_CERT
;
1062 return net::UNKNOWN_CERT
;
1065 } // namespace mozilla_security_manager