From 5c51876fc45efafe4b9d918553c7b32a854ed8ed Mon Sep 17 00:00:00 2001
From: "bulach@chromium.org"
 <bulach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>
Date: Mon, 25 Oct 2010 12:59:54 +0000
Subject: More UI-related OpenSSL support. Refactors a few functions from
 nsNSSCertHelper into common. (no functional change when using NSS).
 Implements some of the x509_certificate_model functions for OpenSSL.

BUG=none
TEST=Compile w/ use_openssl=1, check that the fields in certificate viewer are displayed.

Review URL: http://codereview.chromium.org/3815012

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@63723 0039d316-1c4b-4281-b951-d872f2087c98
---
 net/base/x509_certificate_openssl.cc | 101 +++++++---------------------------
 net/base/x509_openssl_util.cc        | 104 +++++++++++++++++++++++++++++++++++
 net/base/x509_openssl_util.h         |  39 +++++++++++++
 net/net.gyp                          |   4 ++
 4 files changed, 166 insertions(+), 82 deletions(-)
 create mode 100644 net/base/x509_openssl_util.cc
 create mode 100644 net/base/x509_openssl_util.h

(limited to 'net')

diff --git a/net/base/x509_certificate_openssl.cc b/net/base/x509_certificate_openssl.cc
index 444b5d4..4a7beaa 100644
--- a/net/base/x509_certificate_openssl.cc
+++ b/net/base/x509_certificate_openssl.cc
@@ -20,9 +20,12 @@
 #include "net/base/cert_verify_result.h"
 #include "net/base/net_errors.h"
 #include "net/base/openssl_util.h"
+#include "net/base/x509_openssl_util.h"
 
 namespace net {
 
+namespace nxou = net::x509_openssl_util;
+
 namespace {
 
 void CreateOSCertHandlesFromPKCS7Bytes(
@@ -51,39 +54,13 @@ void CreateOSCertHandlesFromPKCS7Bytes(
   }
 }
 
-bool ParsePrincipalFieldInternal(X509_NAME* name,
-                                 int index,
-                                 std::string* field) {
-  ASN1_STRING* data =
-      X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, index));
-  if (!data)
-    return false;
-
-  unsigned char* buf = NULL;
-  int len = ASN1_STRING_to_UTF8(&buf, data);
-  if (len <= 0)
-    return false;
-
-  field->assign(reinterpret_cast<const char*>(buf), len);
-  OPENSSL_free(buf);
-  return true;
-}
-
-void ParsePrincipalField(X509_NAME* name, int nid, std::string* field) {
-  int index = X509_NAME_get_index_by_NID(name, nid, -1);
-  if (index < 0)
-    return;
-
-  ParsePrincipalFieldInternal(name, index, field);
-}
-
-void ParsePrincipalFields(X509_NAME* name,
+void ParsePrincipalValues(X509_NAME* name,
                           int nid,
                           std::vector<std::string>* fields) {
   for (int index = -1;
        (index = X509_NAME_get_index_by_NID(name, nid, index)) != -1;) {
     std::string field;
-    if (!ParsePrincipalFieldInternal(name, index, &field))
+    if (!nxou::ParsePrincipalValueByIndex(name, index, &field))
       break;
     fields->push_back(field);
   }
@@ -95,64 +72,24 @@ void ParsePrincipal(X509Certificate::OSCertHandle cert,
   if (!x509_name)
     return;
 
-  ParsePrincipalFields(x509_name, NID_streetAddress,
+  ParsePrincipalValues(x509_name, NID_streetAddress,
                        &principal->street_addresses);
-  ParsePrincipalFields(x509_name, NID_organizationName,
+  ParsePrincipalValues(x509_name, NID_organizationName,
                        &principal->organization_names);
-  ParsePrincipalFields(x509_name, NID_organizationalUnitName,
+  ParsePrincipalValues(x509_name, NID_organizationalUnitName,
                        &principal->organization_unit_names);
-  ParsePrincipalFields(x509_name, NID_domainComponent,
+  ParsePrincipalValues(x509_name, NID_domainComponent,
                        &principal->domain_components);
 
-  ParsePrincipalField(x509_name, NID_commonName, &principal->common_name);
-  ParsePrincipalField(x509_name, NID_localityName, &principal->locality_name);
-  ParsePrincipalField(x509_name, NID_stateOrProvinceName,
-                      &principal->state_or_province_name);
-  ParsePrincipalField(x509_name, NID_countryName, &principal->country_name);
-}
-
-void ParseDate(ASN1_TIME* x509_time, base::Time* time) {
-  if (!x509_time ||
-      (x509_time->type != V_ASN1_UTCTIME &&
-       x509_time->type != V_ASN1_GENERALIZEDTIME))
-    return;
-
-  std::string str_date(reinterpret_cast<char*>(x509_time->data),
-                       x509_time->length);
-  // UTCTime: YYMMDDHHMMSSZ
-  // GeneralizedTime: YYYYMMDDHHMMSSZ
-  size_t year_length = x509_time->type == V_ASN1_UTCTIME ? 2 : 4;
-  size_t fields_offset = x509_time->type == V_ASN1_UTCTIME ? 0 : 2;
-
-  if (str_date.length() < 11 + year_length)
-    return;
+  nxou::ParsePrincipalValueByNID(x509_name, NID_commonName,
+                                 &principal->common_name);
+  nxou::ParsePrincipalValueByNID(x509_name, NID_localityName,
+                                 &principal->locality_name);
+  nxou::ParsePrincipalValueByNID(x509_name, NID_stateOrProvinceName,
+                                 &principal->state_or_province_name);
+  nxou::ParsePrincipalValueByNID(x509_name, NID_countryName,
+                                 &principal->country_name);
 
-  base::Time::Exploded exploded = {0};
-  bool valid = base::StringToInt(str_date.begin(),
-                                 str_date.begin() + year_length,
-                                 &exploded.year);
-  if (valid && year_length == 2)
-    exploded.year += exploded.year < 50 ? 2000 : 1900;
-
-  valid &= base::StringToInt(str_date.begin() + fields_offset + 2,
-                             str_date.begin() + fields_offset + 4,
-                             &exploded.month);
-  valid &= base::StringToInt(str_date.begin() + fields_offset + 4,
-                             str_date.begin() + fields_offset + 6),
-                             &exploded.day_of_month);
-  valid &= base::StringToInt(str_date.begin() + fields_offset + 6,
-                             str_date.begin() + fields_offset + 8),
-                             &exploded.hour);
-  valid &= base::StringToInt(str_date.begin() + fields_offset + 8,
-                             str_date.begin() + fields_offset + 10),
-                             &exploded.minute);
-  valid &= base::StringToInt(str_date.begin() + fields_offset + 10,
-                             str_date.begin() + fields_offset + 12,
-                             &exploded.second);
-
-  DCHECK(valid);
-
-  *time = base::Time::FromUTCExploded(exploded);
 }
 
 void ParseSubjectAltNames(X509Certificate::OSCertHandle cert,
@@ -357,8 +294,8 @@ void X509Certificate::Initialize() {
   fingerprint_ = CalculateFingerprint(cert_handle_);
   ParsePrincipal(cert_handle_, X509_get_subject_name(cert_handle_), &subject_);
   ParsePrincipal(cert_handle_, X509_get_issuer_name(cert_handle_), &issuer_);
-  ParseDate(X509_get_notBefore(cert_handle_), &valid_start_);
-  ParseDate(X509_get_notAfter(cert_handle_), &valid_expiry_);
+  nxou::ParseDate(X509_get_notBefore(cert_handle_), &valid_start_);
+  nxou::ParseDate(X509_get_notAfter(cert_handle_), &valid_expiry_);
 }
 
 SHA1Fingerprint X509Certificate::CalculateFingerprint(OSCertHandle cert) {
diff --git a/net/base/x509_openssl_util.cc b/net/base/x509_openssl_util.cc
new file mode 100644
index 0000000..5eb4e3f
--- /dev/null
+++ b/net/base/x509_openssl_util.cc
@@ -0,0 +1,104 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/base/x509_openssl_util.h"
+
+#include "base/logging.h"
+#include "base/string_number_conversions.h"
+#include "base/time.h"
+
+namespace net {
+
+namespace x509_openssl_util {
+
+bool ParsePrincipalKeyAndValueByIndex(X509_NAME* name,
+                                      int index,
+                                      std::string* key,
+                                      std::string* value) {
+  X509_NAME_ENTRY* entry = X509_NAME_get_entry(name, index);
+  if (!entry)
+    return false;
+
+  if (key) {
+    ASN1_OBJECT* object = X509_NAME_ENTRY_get_object(entry);
+    key->assign(OBJ_nid2sn(OBJ_obj2nid(object)));
+  }
+
+  ASN1_STRING* data = X509_NAME_ENTRY_get_data(entry);
+  if (!data)
+    return false;
+
+  unsigned char* buf = NULL;
+  int len = ASN1_STRING_to_UTF8(&buf, data);
+  if (len <= 0)
+    return false;
+
+  value->assign(reinterpret_cast<const char*>(buf), len);
+  OPENSSL_free(buf);
+  return true;
+}
+
+bool ParsePrincipalValueByIndex(X509_NAME* name,
+                                int index,
+                                std::string* value) {
+  return ParsePrincipalKeyAndValueByIndex(name, index, NULL, value);
+}
+
+bool ParsePrincipalValueByNID(X509_NAME* name, int nid, std::string* value) {
+  int index = X509_NAME_get_index_by_NID(name, nid, -1);
+  if (index < 0)
+    return false;
+
+  return ParsePrincipalValueByIndex(name, index, value);
+}
+
+bool ParseDate(ASN1_TIME* x509_time, base::Time* time) {
+  if (!x509_time ||
+      (x509_time->type != V_ASN1_UTCTIME &&
+       x509_time->type != V_ASN1_GENERALIZEDTIME))
+    return false;
+
+  std::string str_date(reinterpret_cast<char*>(x509_time->data),
+                       x509_time->length);
+  // UTCTime: YYMMDDHHMMSSZ
+  // GeneralizedTime: YYYYMMDDHHMMSSZ
+  size_t year_length = x509_time->type == V_ASN1_UTCTIME ? 2 : 4;
+  size_t fields_offset = x509_time->type == V_ASN1_UTCTIME ? 0 : 2;
+
+  if (str_date.length() < 11 + year_length)
+    return false;
+
+  base::Time::Exploded exploded = {0};
+  bool valid = base::StringToInt(str_date.begin(),
+                                 str_date.begin() + year_length,
+                                 &exploded.year);
+  if (valid && year_length == 2)
+    exploded.year += exploded.year < 50 ? 2000 : 1900;
+
+  valid &= base::StringToInt(str_date.begin() + fields_offset + 2,
+                             str_date.begin() + fields_offset + 4,
+                             &exploded.month);
+  valid &= base::StringToInt(str_date.begin() + fields_offset + 4,
+                             str_date.begin() + fields_offset + 6,
+                             &exploded.day_of_month);
+  valid &= base::StringToInt(str_date.begin() + fields_offset + 6,
+                             str_date.begin() + fields_offset + 8,
+                             &exploded.hour);
+  valid &= base::StringToInt(str_date.begin() + fields_offset + 8,
+                             str_date.begin() + fields_offset + 10,
+                             &exploded.minute);
+  valid &= base::StringToInt(str_date.begin() + fields_offset + 10,
+                             str_date.begin() + fields_offset + 12,
+                             &exploded.second);
+
+  if (!valid)
+    return false;
+
+  *time = base::Time::FromUTCExploded(exploded);
+  return valid;
+}
+
+} // namespace x509_openssl_util
+
+} // namespace net
diff --git a/net/base/x509_openssl_util.h b/net/base/x509_openssl_util.h
new file mode 100644
index 0000000..5ac511b
--- /dev/null
+++ b/net/base/x509_openssl_util.h
@@ -0,0 +1,39 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_BASE_X509_OPENSSL_UTIL_H_
+#define NET_BASE_X509_OPENSSL_UTIL_H_
+#pragma once
+
+#include <openssl/asn1.h>
+#include <openssl/x509v3.h>
+
+#include <string>
+
+namespace base {
+class Time;
+}  // namespace base
+
+namespace net {
+
+// A collection of helper functions to fetch data from OpenSSL X509 certificates
+// into more convenient std / base datatypes.
+namespace x509_openssl_util {
+
+bool ParsePrincipalKeyAndValueByIndex(X509_NAME* name,
+                                      int index,
+                                      std::string* key,
+                                      std::string* value);
+
+bool ParsePrincipalValueByIndex(X509_NAME* name, int index, std::string* value);
+
+bool ParsePrincipalValueByNID(X509_NAME* name, int nid, std::string* value);
+
+bool ParseDate(ASN1_TIME* x509_time, base::Time* time);
+
+} // namespace x509_openssl_util
+
+} // namespace net
+
+#endif  // NET_BASE_X509_OPENSSL_UTIL_H_
diff --git a/net/net.gyp b/net/net.gyp
index 8e01f57..4a2db1b 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -196,6 +196,8 @@
         'base/x509_cert_types.cc',
         'base/x509_cert_types.h',
         'base/x509_cert_types_mac.cc',
+        'base/x509_openssl_util.cc',
+        'base/x509_openssl_util.h',
         'third_party/mozilla_security_manager/nsKeygenHandler.cpp',
         'third_party/mozilla_security_manager/nsKeygenHandler.h',
         'third_party/mozilla_security_manager/nsNSSCertificateDB.cpp',
@@ -288,6 +290,8 @@
               'base/openssl_util.cc',
               'base/openssl_util.h',
               'base/x509_certificate_openssl.cc',
+              'base/x509_openssl_util.cc',
+              'base/x509_openssl_util.h',
              ],
           },
         ],
-- 
cgit v1.1