1 /* 2 * libjingle 3 * Copyright 2011, Google Inc. 4 * Portions Copyright 2011, RTFM, Inc. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 20 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 26 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <string> 30 31 #include "talk/base/gunit.h" 32 #include "talk/base/ssladapter.h" 33 #include "talk/base/sslidentity.h" 34 35 using talk_base::SSLIdentity; 36 37 const char kTestCertificate[] = "-----BEGIN CERTIFICATE-----\n" 38 "MIIB6TCCAVICAQYwDQYJKoZIhvcNAQEEBQAwWzELMAkGA1UEBhMCQVUxEzARBgNV\n" 39 "BAgTClF1ZWVuc2xhbmQxGjAYBgNVBAoTEUNyeXB0U29mdCBQdHkgTHRkMRswGQYD\n" 40 "VQQDExJUZXN0IENBICgxMDI0IGJpdCkwHhcNMDAxMDE2MjIzMTAzWhcNMDMwMTE0\n" 41 "MjIzMTAzWjBjMQswCQYDVQQGEwJBVTETMBEGA1UECBMKUXVlZW5zbGFuZDEaMBgG\n" 42 "A1UEChMRQ3J5cHRTb2Z0IFB0eSBMdGQxIzAhBgNVBAMTGlNlcnZlciB0ZXN0IGNl\n" 43 "cnQgKDUxMiBiaXQpMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJ+zw4Qnlf8SMVIP\n" 44 "Fe9GEcStgOY2Ww/dgNdhjeD8ckUJNP5VZkVDTGiXav6ooKXfX3j/7tdkuD8Ey2//\n" 45 "Kv7+ue0CAwEAATANBgkqhkiG9w0BAQQFAAOBgQCT0grFQeZaqYb5EYfk20XixZV4\n" 46 "GmyAbXMftG1Eo7qGiMhYzRwGNWxEYojf5PZkYZXvSqZ/ZXHXa4g59jK/rJNnaVGM\n" 47 "k+xIX8mxQvlV0n5O9PIha5BX5teZnkHKgL8aKKLKW1BK7YTngsfSzzaeame5iKfz\n" 48 "itAE+OjGF+PFKbwX8Q==\n" 49 "-----END CERTIFICATE-----\n"; 50 51 const unsigned char kTestCertSha1[] = {0xA6, 0xC8, 0x59, 0xEA, 52 0xC3, 0x7E, 0x6D, 0x33, 53 0xCF, 0xE2, 0x69, 0x9D, 54 0x74, 0xE6, 0xF6, 0x8A, 55 0x9E, 0x47, 0xA7, 0xCA}; 56 57 class SSLIdentityTest : public testing::Test { 58 public: 59 SSLIdentityTest() : 60 identity1_(), identity2_() { 61 } 62 63 ~SSLIdentityTest() { 64 } 65 66 static void SetUpTestCase() { 67 talk_base::InitializeSSL(); 68 } 69 70 static void TearDownTestCase() { 71 talk_base::CleanupSSL(); 72 } 73 74 virtual void SetUp() { 75 identity1_.reset(SSLIdentity::Generate("test1")); 76 identity2_.reset(SSLIdentity::Generate("test2")); 77 78 ASSERT_TRUE(identity1_); 79 ASSERT_TRUE(identity2_); 80 81 test_cert_.reset( 82 talk_base::SSLCertificate::FromPEMString(kTestCertificate)); 83 ASSERT_TRUE(test_cert_); 84 } 85 86 void TestGetSignatureDigestAlgorithm() { 87 std::string digest_algorithm; 88 // Both NSSIdentity::Generate and OpenSSLIdentity::Generate are 89 // hard-coded to generate RSA-SHA1 certificates. 90 ASSERT_TRUE(identity1_->certificate().GetSignatureDigestAlgorithm( 91 &digest_algorithm)); 92 ASSERT_EQ(talk_base::DIGEST_SHA_1, digest_algorithm); 93 ASSERT_TRUE(identity2_->certificate().GetSignatureDigestAlgorithm( 94 &digest_algorithm)); 95 ASSERT_EQ(talk_base::DIGEST_SHA_1, digest_algorithm); 96 97 // The test certificate has an MD5-based signature. 98 ASSERT_TRUE(test_cert_->GetSignatureDigestAlgorithm(&digest_algorithm)); 99 ASSERT_EQ(talk_base::DIGEST_MD5, digest_algorithm); 100 } 101 102 void TestDigest(const std::string &algorithm, size_t expected_len, 103 const unsigned char *expected_digest = NULL) { 104 unsigned char digest1[64]; 105 unsigned char digest1b[64]; 106 unsigned char digest2[64]; 107 size_t digest1_len; 108 size_t digest1b_len; 109 size_t digest2_len; 110 bool rv; 111 112 rv = identity1_->certificate().ComputeDigest(algorithm, 113 digest1, sizeof(digest1), 114 &digest1_len); 115 EXPECT_TRUE(rv); 116 EXPECT_EQ(expected_len, digest1_len); 117 118 rv = identity1_->certificate().ComputeDigest(algorithm, 119 digest1b, sizeof(digest1b), 120 &digest1b_len); 121 EXPECT_TRUE(rv); 122 EXPECT_EQ(expected_len, digest1b_len); 123 EXPECT_EQ(0, memcmp(digest1, digest1b, expected_len)); 124 125 126 rv = identity2_->certificate().ComputeDigest(algorithm, 127 digest2, sizeof(digest2), 128 &digest2_len); 129 EXPECT_TRUE(rv); 130 EXPECT_EQ(expected_len, digest2_len); 131 EXPECT_NE(0, memcmp(digest1, digest2, expected_len)); 132 133 // If we have an expected hash for the test cert, check it. 134 if (expected_digest) { 135 unsigned char digest3[64]; 136 size_t digest3_len; 137 138 rv = test_cert_->ComputeDigest(algorithm, digest3, sizeof(digest3), 139 &digest3_len); 140 EXPECT_TRUE(rv); 141 EXPECT_EQ(expected_len, digest3_len); 142 EXPECT_EQ(0, memcmp(digest3, expected_digest, expected_len)); 143 } 144 } 145 146 private: 147 talk_base::scoped_ptr<SSLIdentity> identity1_; 148 talk_base::scoped_ptr<SSLIdentity> identity2_; 149 talk_base::scoped_ptr<talk_base::SSLCertificate> test_cert_; 150 }; 151 152 TEST_F(SSLIdentityTest, DigestSHA1) { 153 TestDigest(talk_base::DIGEST_SHA_1, 20, kTestCertSha1); 154 } 155 156 // HASH_AlgSHA224 is not supported in the chromium linux build. 157 #if SSL_USE_NSS 158 TEST_F(SSLIdentityTest, DISABLED_DigestSHA224) { 159 #else 160 TEST_F(SSLIdentityTest, DigestSHA224) { 161 #endif 162 TestDigest(talk_base::DIGEST_SHA_224, 28); 163 } 164 165 TEST_F(SSLIdentityTest, DigestSHA256) { 166 TestDigest(talk_base::DIGEST_SHA_256, 32); 167 } 168 169 TEST_F(SSLIdentityTest, DigestSHA384) { 170 TestDigest(talk_base::DIGEST_SHA_384, 48); 171 } 172 173 TEST_F(SSLIdentityTest, DigestSHA512) { 174 TestDigest(talk_base::DIGEST_SHA_512, 64); 175 } 176 177 TEST_F(SSLIdentityTest, FromPEMStrings) { 178 static const char kRSA_PRIVATE_KEY_PEM[] = 179 "-----BEGIN RSA PRIVATE KEY-----\n" 180 "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMYRkbhmI7kVA/rM\n" 181 "czsZ+6JDhDvnkF+vn6yCAGuRPV03zuRqZtDy4N4to7PZu9PjqrRl7nDMXrG3YG9y\n" 182 "rlIAZ72KjcKKFAJxQyAKLCIdawKRyp8RdK3LEySWEZb0AV58IadqPZDTNHHRX8dz\n" 183 "5aTSMsbbkZ+C/OzTnbiMqLL/vg6jAgMBAAECgYAvgOs4FJcgvp+TuREx7YtiYVsH\n" 184 "mwQPTum2z/8VzWGwR8BBHBvIpVe1MbD/Y4seyI2aco/7UaisatSgJhsU46/9Y4fq\n" 185 "2TwXH9QANf4at4d9n/R6rzwpAJOpgwZgKvdQjkfrKTtgLV+/dawvpxUYkRH4JZM1\n" 186 "CVGukMfKNrSVH4Ap4QJBAOJmGV1ASPnB4r4nc99at7JuIJmd7fmuVUwUgYi4XgaR\n" 187 "WhScBsgYwZ/JoywdyZJgnbcrTDuVcWG56B3vXbhdpMsCQQDf9zeJrjnPZ3Cqm79y\n" 188 "kdqANep0uwZciiNiWxsQrCHztywOvbFhdp8iYVFG9EK8DMY41Y5TxUwsHD+67zao\n" 189 "ZNqJAkEA1suLUP/GvL8IwuRneQd2tWDqqRQ/Td3qq03hP7e77XtF/buya3Ghclo5\n" 190 "54czUR89QyVfJEC6278nzA7n2h1uVQJAcG6mztNL6ja/dKZjYZye2CY44QjSlLo0\n" 191 "MTgTSjdfg/28fFn2Jjtqf9Pi/X+50LWI/RcYMC2no606wRk9kyOuIQJBAK6VSAim\n" 192 "1pOEjsYQn0X5KEIrz1G3bfCbB848Ime3U2/FWlCHMr6ch8kCZ5d1WUeJD3LbwMNG\n" 193 "UCXiYxSsu20QNVw=\n" 194 "-----END RSA PRIVATE KEY-----\n"; 195 196 static const char kCERT_PEM[] = 197 "-----BEGIN CERTIFICATE-----\n" 198 "MIIBmTCCAQKgAwIBAgIEbzBSAjANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDEwZX\n" 199 "ZWJSVEMwHhcNMTQwMTAyMTgyNDQ3WhcNMTQwMjAxMTgyNDQ3WjARMQ8wDQYDVQQD\n" 200 "EwZXZWJSVEMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMYRkbhmI7kVA/rM\n" 201 "czsZ+6JDhDvnkF+vn6yCAGuRPV03zuRqZtDy4N4to7PZu9PjqrRl7nDMXrG3YG9y\n" 202 "rlIAZ72KjcKKFAJxQyAKLCIdawKRyp8RdK3LEySWEZb0AV58IadqPZDTNHHRX8dz\n" 203 "5aTSMsbbkZ+C/OzTnbiMqLL/vg6jAgMBAAEwDQYJKoZIhvcNAQELBQADgYEAUflI\n" 204 "VUe5Krqf5RVa5C3u/UTAOAUJBiDS3VANTCLBxjuMsvqOG0WvaYWP3HYPgrz0jXK2\n" 205 "LJE/mGw3MyFHEqi81jh95J+ypl6xKW6Rm8jKLR87gUvCaVYn/Z4/P3AqcQTB7wOv\n" 206 "UD0A8qfhfDM+LK6rPAnCsVN0NRDY3jvd6rzix9M=\n" 207 "-----END CERTIFICATE-----\n"; 208 209 talk_base::scoped_ptr<SSLIdentity> identity( 210 SSLIdentity::FromPEMStrings(kRSA_PRIVATE_KEY_PEM, kCERT_PEM)); 211 EXPECT_TRUE(identity); 212 EXPECT_EQ(kCERT_PEM, identity->certificate().ToPEMString()); 213 } 214 215 TEST_F(SSLIdentityTest, PemDerConversion) { 216 std::string der; 217 EXPECT_TRUE(SSLIdentity::PemToDer("CERTIFICATE", kTestCertificate, &der)); 218 219 EXPECT_EQ(kTestCertificate, SSLIdentity::DerToPem( 220 "CERTIFICATE", 221 reinterpret_cast<const unsigned char*>(der.data()), der.length())); 222 } 223 224 TEST_F(SSLIdentityTest, GetSignatureDigestAlgorithm) { 225 TestGetSignatureDigestAlgorithm(); 226 } 227