Commit 43ab2622 authored by Maksim Ivanov's avatar Maksim Ivanov Committed by Commit Bot

Stop using certs from //net in platform_keys tests

Fix the tests of the platform_keys APIs to use their own test
certificates and keys instead of the ones from
//net/data/ssl/certificates.

This should fix troubles happening when people try to update certs in
//net, because platform_keys' tests were containing some additional data
files that contained information derived from //net's certs. People had
to know that besides updating //net's certs they need to go to
platform_keys tests and regenerate additional files using the special
script.

This CL changes the platform_keys tests to be bundled with their own
certificates/keys hermetically, without containing any derivatives of
//net's certs anymore.

Bug: 591193
Test: regenerate all certs in //net/data/ssl/certificates, check that *PlatformKeys* unit_tests and browser_tests pass
Change-Id: I2e4026d6d7b2f10e382b507c62dec2397432d070
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1825359Reviewed-by: default avatarDavid Benjamin <davidben@chromium.org>
Commit-Queue: Maksim Ivanov <emaxx@chromium.org>
Cr-Commit-Position: refs/heads/master@{#701736}
parent 4a580f5f
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
#include <utility> #include <utility>
#include "base/bind.h" #include "base/bind.h"
#include "base/json/json_writer.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
...@@ -28,8 +27,8 @@ ...@@ -28,8 +27,8 @@
#include "crypto/scoped_test_system_nss_key_slot.h" #include "crypto/scoped_test_system_nss_key_slot.h"
#include "net/cert/nss_cert_database.h" #include "net/cert/nss_cert_database.h"
#include "net/cert/test_root_certs.h" #include "net/cert/test_root_certs.h"
#include "net/cert/x509_certificate.h"
#include "net/test/cert_test_util.h" #include "net/test/cert_test_util.h"
#include "net/test/test_data_directory.h"
namespace { namespace {
...@@ -160,6 +159,10 @@ class PlatformKeysTest : public PlatformKeysTestBase { ...@@ -160,6 +159,10 @@ class PlatformKeysTest : public PlatformKeysTestBase {
const extensions::Extension* extension_; const extensions::Extension* extension_;
private: private:
base::FilePath extension_path() const {
return test_data_dir_.AppendASCII("platform_keys");
}
void SetPrivateSoftwareSlotOnIO(crypto::ScopedPK11Slot slot) { void SetPrivateSoftwareSlotOnIO(crypto::ScopedPK11Slot slot) {
crypto::SetPrivateSoftwareSlotForChromeOSUserForTesting(std::move(slot)); crypto::SetPrivateSoftwareSlotForChromeOSUserForTesting(std::move(slot));
} }
...@@ -193,25 +196,23 @@ class PlatformKeysTest : public PlatformKeysTestBase { ...@@ -193,25 +196,23 @@ class PlatformKeysTest : public PlatformKeysTestBase {
? cert_db->GetPrivateSlot() ? cert_db->GetPrivateSlot()
: cert_db->GetPublicSlot(); : cert_db->GetPublicSlot();
client_cert1_ = net::ImportClientCertAndKeyFromFile( client_cert1_ = net::ImportClientCertAndKeyFromFile(
net::GetTestCertsDirectory(), "client_1.pem", "client_1.pk8", extension_path(), "client_1.pem", "client_1.pk8", slot.get());
slot.get());
ASSERT_TRUE(client_cert1_.get()); ASSERT_TRUE(client_cert1_.get());
// Import a second client cert signed by another CA than client_1 into the // Import a second client cert signed by another CA than client_1 into the
// system wide key slot. // system wide key slot.
client_cert2_ = net::ImportClientCertAndKeyFromFile( client_cert2_ = net::ImportClientCertAndKeyFromFile(
net::GetTestCertsDirectory(), "client_2.pem", "client_2.pk8", extension_path(), "client_2.pem", "client_2.pk8",
test_system_slot()->slot()); test_system_slot()->slot());
ASSERT_TRUE(client_cert2_.get()); ASSERT_TRUE(client_cert2_.get());
} }
void SetupTestCACerts() { void SetupTestCACerts() {
net::TestRootCerts* root_certs = net::TestRootCerts::GetInstance(); net::TestRootCerts* root_certs = net::TestRootCerts::GetInstance();
// "root_ca_cert.pem" is the issuer of "ok_cert.pem" which is loaded on the // "root.pem" is the issuer of the "l1_leaf.pem" and (transitively)
// JS side. Generated by create_test_certs.sh . // "l1_leaf.pem" certs which are loaded on the JS side. Generated by
base::FilePath extension_path = test_data_dir_.AppendASCII("platform_keys"); // create_test_certs.sh .
root_certs->AddFromFile( root_certs->AddFromFile(extension_path().AppendASCII("root.pem"));
test_data_dir_.AppendASCII("platform_keys").AppendASCII("root.pem"));
} }
const bool key_permission_policy_; const bool key_permission_policy_;
......
CA_DIR=out
[ca]
default_ca = ca_settings
[ca_settings]
database = $CA_DIR/${ENV::ID}-index.txt
new_certs_dir = $CA_DIR
serial = $CA_DIR/${ENV::ID}-serial
certificate = $CA_DIR/${ENV::ID}.pem
private_key = $CA_DIR/${ENV::ID}.key
default_md = sha256
default_days = 3650
policy = policy_anything
unique_subject = no
copy_extensions = copy
[policy_anything]
# Default signing policy
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = optional
emailAddress = optional
[req]
default_bits = 2048
default_md = sha256
string_mask = utf8only
prompt = no
encrypt_key = no
distinguished_name = req_env_dn
[user_cert]
# Extensions to add when signing a request for an EE cert
basicConstraints = critical, CA:false
extendedKeyUsage = serverAuth,clientAuth
[ca_cert]
# Extensions to add when signing a request for an intermediate/CA cert
basicConstraints = critical, CA:true
keyUsage = critical, keyCertSign, cRLSign
[req_env_dn]
CN = ${ENV::COMMON_NAME}
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 4097 (0x1001)
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN=Client Cert 1 CA
Validity
Not Before: Sep 25 20:39:04 2019 GMT
Not After : Sep 22 20:39:04 2029 GMT
Subject: CN=Client Cert 1
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (2048 bit)
Modulus:
00:c1:3b:f6:38:22:92:9f:05:43:87:8c:33:a5:13:
88:12:2b:6a:c2:25:a7:5a:4f:0a:d0:f0:60:43:21:
05:62:84:37:cc:85:2c:c1:e5:f3:94:4f:b5:e6:3f:
34:97:75:3f:d0:d1:cc:70:f9:e4:38:b8:82:6c:5e:
74:be:e8:f0:c4:a1:23:84:05:3e:5f:ad:79:f9:bf:
c8:44:d7:b6:b6:c7:87:5f:cc:25:05:e6:cb:cc:65:
62:2f:47:5d:0a:b5:ab:3d:be:6c:b7:b0:a8:fb:1e:
97:cf:cf:a2:5f:79:5d:d5:9d:49:0b:16:c5:69:24:
46:ca:10:bb:5a:55:3a:c0:c0:4d:7f:f7:8f:55:0e:
7c:f0:59:c4:da:50:70:1a:0a:5c:d1:15:d2:fa:1c:
9f:7b:3c:bc:dc:27:63:69:3c:ab:e8:c8:48:56:29:
9e:1d:f5:77:0a:c3:05:98:98:a1:f5:a7:93:e7:ef:
7f:f9:e8:b6:7b:52:47:39:f3:26:e9:eb:42:19:a8:
b2:91:67:cc:fb:57:5c:bf:bd:15:da:82:e0:bf:77:
16:ea:76:b3:73:c8:05:73:d9:ae:25:a2:c1:bd:24:
99:90:f7:06:84:09:fe:e5:c8:5c:68:1e:ed:81:c4:
03:18:fd:29:d5:0f:a9:12:c4:19:b0:a5:b6:3c:2b:
49:97
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication
Signature Algorithm: sha256WithRSAEncryption
55:cf:2b:7a:e0:80:2b:28:44:b8:2d:84:60:a4:b8:1f:b9:c6:
6c:80:9d:60:ea:60:f6:e2:b3:09:9a:ce:b2:53:e1:51:c5:eb:
33:89:5b:51:b7:af:25:44:d8:41:b7:53:e8:0d:e0:26:6c:0a:
66:a4:99:d4:3a:ac:04:d9:12:fc:82:c6:ea:37:e6:64:71:a1:
b6:91:4b:28:68:c8:d9:0d:22:f6:8f:64:1c:61:40:34:27:bd:
cf:da:d2:48:0b:89:5f:e7:11:13:af:2e:28:2f:a2:9d:57:93:
3b:8d:9d:0f:31:c3:29:a3:1d:33:6a:4b:05:25:a1:70:ca:9a:
18:f2:92:03:2b:aa:37:fe:45:d1:f1:64:7d:8d:a9:76:f6:cf:
5b:ac:70:c0:12:a4:b9:3f:06:a7:45:62:a7:54:4c:d5:70:5c:
99:92:5d:16:b0:f5:cf:12:ed:dc:a9:ac:c7:31:81:52:91:21:
36:22:eb:2f:77:6a:e3:13:82:6a:b5:17:73:ee:a9:9e:83:73:
83:9d:b6:80:eb:85:b2:bd:7d:d5:42:30:3e:2c:e2:ca:e3:2d:
4b:bf:c6:59:40:86:d9:d4:a6:90:d5:36:2f:8f:11:ba:d2:a5:
ad:1b:b0:6c:4e:e0:ad:bc:d8:38:90:fd:3c:6d:71:20:2a:9f:
ea:78:4d:79
-----BEGIN CERTIFICATE-----
MIIC3jCCAcagAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwGzEZMBcGA1UEAwwQQ2xp
ZW50IENlcnQgMSBDQTAeFw0xOTA5MjUyMDM5MDRaFw0yOTA5MjIyMDM5MDRaMBgx
FjAUBgNVBAMMDUNsaWVudCBDZXJ0IDEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
ggEKAoIBAQDBO/Y4IpKfBUOHjDOlE4gSK2rCJadaTwrQ8GBDIQVihDfMhSzB5fOU
T7XmPzSXdT/Q0cxw+eQ4uIJsXnS+6PDEoSOEBT5frXn5v8hE17a2x4dfzCUF5svM
ZWIvR10Ktas9vmy3sKj7HpfPz6JfeV3VnUkLFsVpJEbKELtaVTrAwE1/949VDnzw
WcTaUHAaClzRFdL6HJ97PLzcJ2NpPKvoyEhWKZ4d9XcKwwWYmKH1p5Pn73/56LZ7
Ukc58ybp60IZqLKRZ8z7V1y/vRXaguC/dxbqdrNzyAVz2a4losG9JJmQ9waECf7l
yFxoHu2BxAMY/SnVD6kSxBmwpbY8K0mXAgMBAAGjLzAtMAwGA1UdEwEB/wQCMAAw
HQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IB
AQBVzyt64IArKES4LYRgpLgfucZsgJ1g6mD24rMJms6yU+FRxesziVtRt68lRNhB
t1PoDeAmbApmpJnUOqwE2RL8gsbqN+ZkcaG2kUsoaMjZDSL2j2QcYUA0J73P2tJI
C4lf5xETry4oL6KdV5M7jZ0PMcMpox0zaksFJaFwypoY8pIDK6o3/kXR8WR9jal2
9s9brHDAEqS5PwanRWKnVEzVcFyZkl0WsPXPEu3cqazHMYFSkSE2Iusvd2rjE4Jq
tRdz7qmeg3ODnbaA64WyvX3VQjA+LOLK4y1Lv8ZZQIbZ1KaQ1TYvjxG60qWtG7Bs
TuCtvNg4kP08bXEgKp/qeE15
-----END CERTIFICATE-----
01 0 U B CA 010U Client Cert 1 CA
\ No newline at end of file \ No newline at end of file
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 4098 (0x1002)
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN=Client Cert 2 CA
Validity
Not Before: Sep 25 20:39:04 2019 GMT
Not After : Sep 22 20:39:04 2029 GMT
Subject: CN=Client Cert 2
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (2048 bit)
Modulus:
00:d8:75:47:d7:df:06:33:37:0d:30:55:09:be:41:
aa:87:e2:aa:d6:df:8e:6b:7b:18:ad:d0:2c:40:08:
d5:71:3a:66:74:d0:90:03:93:1d:ba:17:0a:80:a7:
ea:8e:02:1f:ab:ed:5c:65:78:84:25:f4:99:2d:e6:
8f:b1:f6:d7:50:66:bf:25:76:ea:22:1f:7f:b3:f3:
ec:4b:65:74:9c:7b:4f:8d:3e:43:dd:33:fa:67:26:
22:f5:ca:75:d7:bf:85:e0:22:3b:2b:a8:3b:5e:d1:
65:53:da:89:40:39:f9:1f:5b:74:10:f3:ee:c4:84:
43:5f:ed:f5:14:91:bd:4b:cf:fc:dd:7e:8c:8f:b2:
e4:45:95:67:93:90:47:66:f1:32:ce:09:87:bb:d2:
1e:cd:34:34:40:23:9e:51:e5:04:db:c1:70:80:95:
3b:47:04:4c:91:25:65:47:9e:f7:43:f0:57:e7:c7:
9b:92:d2:4c:89:e9:40:58:b9:60:e9:09:bb:8f:8e:
ab:fa:35:1b:2b:2a:50:52:1a:a3:72:1e:08:f8:70:
2d:0a:85:87:fa:c5:7e:9c:21:e6:90:b8:aa:77:ce:
a9:77:ce:ed:d2:a0:db:73:07:e3:c1:6b:45:9d:4f:
19:d8:a2:b1:24:d6:8b:2c:0f:49:9b:d3:75:ee:75:
6f:73
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication
Signature Algorithm: sha256WithRSAEncryption
17:24:30:da:bd:19:5c:51:e7:cb:d9:6e:e9:81:6c:d9:4e:93:
f5:2d:53:7c:0d:27:69:b6:0b:20:60:94:cd:37:dc:e7:ef:b3:
ca:bc:6c:bf:9a:1f:bf:fa:76:ef:ac:cb:19:c2:f1:bf:4c:b2:
35:e2:01:42:bd:9a:ed:36:3b:15:f0:a6:13:6e:82:7b:72:6a:
dd:19:4b:2b:3c:a6:02:ce:aa:3d:ca:51:7e:15:75:ef:0d:c3:
98:2c:04:d6:40:71:c8:45:be:14:74:b5:5c:7d:9a:f1:db:17:
f4:64:96:05:f3:fb:28:dc:22:d5:7e:e8:96:29:78:68:94:16:
e0:c7:5a:ff:62:34:ee:f4:b8:89:d5:91:a3:20:da:8b:31:90:
d6:6d:cf:f6:d4:5c:03:4e:51:8d:63:7b:c2:9b:f4:a4:76:7f:
b9:09:68:10:55:6c:84:a5:82:67:e7:1b:73:55:28:4f:4b:43:
bc:3a:6c:bf:f8:64:2b:84:6c:97:05:9a:13:99:1f:95:90:69:
2e:a1:74:c0:c9:d3:59:7e:57:59:93:3e:4d:95:94:c9:8c:f5:
d8:86:64:1d:77:a7:51:15:38:1a:05:c1:fe:71:4c:3d:04:a3:
48:76:cb:57:27:4f:0f:81:ee:59:03:5a:e7:50:e1:24:e7:29:
bf:b6:ad:37
-----BEGIN CERTIFICATE-----
MIIC3jCCAcagAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwGzEZMBcGA1UEAwwQQ2xp
ZW50IENlcnQgMiBDQTAeFw0xOTA5MjUyMDM5MDRaFw0yOTA5MjIyMDM5MDRaMBgx
FjAUBgNVBAMMDUNsaWVudCBDZXJ0IDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
ggEKAoIBAQDYdUfX3wYzNw0wVQm+QaqH4qrW345rexit0CxACNVxOmZ00JADkx26
FwqAp+qOAh+r7VxleIQl9Jkt5o+x9tdQZr8lduoiH3+z8+xLZXSce0+NPkPdM/pn
JiL1ynXXv4XgIjsrqDte0WVT2olAOfkfW3QQ8+7EhENf7fUUkb1Lz/zdfoyPsuRF
lWeTkEdm8TLOCYe70h7NNDRAI55R5QTbwXCAlTtHBEyRJWVHnvdD8Ffnx5uS0kyJ
6UBYuWDpCbuPjqv6NRsrKlBSGqNyHgj4cC0KhYf6xX6cIeaQuKp3zql3zu3SoNtz
B+PBa0WdTxnYorEk1ossD0mb03XudW9zAgMBAAGjLzAtMAwGA1UdEwEB/wQCMAAw
HQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IB
AQAXJDDavRlcUefL2W7pgWzZTpP1LVN8DSdptgsgYJTNN9zn77PKvGy/mh+/+nbv
rMsZwvG/TLI14gFCvZrtNjsV8KYTboJ7cmrdGUsrPKYCzqo9ylF+FXXvDcOYLATW
QHHIRb4UdLVcfZrx2xf0ZJYF8/so3CLVfuiWKXholBbgx1r/YjTu9LiJ1ZGjINqL
MZDWbc/21FwDTlGNY3vCm/Skdn+5CWgQVWyEpYJn5xtzVShPS0O8Omy/+GQrhGyX
BZoTmR+VkGkuoXTAydNZfldZkz5NlZTJjPXYhmQdd6dRFTgaBcH+cUw9BKNIdstX
J08Pge5ZA1rnUOEk5ym/tq03
-----END CERTIFICATE-----
#!/bin/bash
# Copyright 2016 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.
# Updates the files which depend on net/data/ssl/certificates.
try() {
"$@" || {
e=$?
echo "*** ERROR $e *** $@ " > /dev/stderr
exit $e
}
}
net_certs_dir=../../../../../../net/data/ssl/certificates
try openssl x509 -in "${net_certs_dir}/client_1.pem" -outform DER -out \
client_1.der
try openssl x509 -in "${net_certs_dir}/client_2.pem" -outform DER -out \
client_2.der
try openssl rsa -in "${net_certs_dir}/client_1.key" -inform PEM -out \
client_1_spki.der -pubout -outform DER
try openssl asn1parse -in client_1.der -inform DER -strparse 32 -out \
client_1_issuer_dn.der
try echo -n "hello world" > data
try openssl rsautl -inkey "${net_certs_dir}/client_1.key" -sign -in \
data -pkcs -out signature_nohash_pkcs
try openssl dgst -sha1 -sign "${net_certs_dir}/client_1.key" -out \
signature_client1_sha1_pkcs data
try openssl dgst -sha1 -sign "${net_certs_dir}/client_2.key" -out \
signature_client2_sha1_pkcs data
...@@ -4,7 +4,14 @@ ...@@ -4,7 +4,14 @@
# Use of this source code is governed by a BSD-style license that can be # Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file. # found in the LICENSE file.
# Generates the following tree of certificates: # Generates the following trees of certificates:
#
# client_root (self-signed root)
# \ \
# \ \--> client_1_ca --> client_1 (end-entity)
# \
# \----> client_2_ca --> client_2 (end-entity)
#
# root (self-signed root) # root (self-signed root)
# \ \ # \ \
# \ \--> l1_leaf (end-entity) # \ \--> l1_leaf (end-entity)
...@@ -19,6 +26,135 @@ export CA_CERT_UTIL_OUT_DIR="./out/" ...@@ -19,6 +26,135 @@ export CA_CERT_UTIL_OUT_DIR="./out/"
try rm -rf out try rm -rf out
try mkdir out try mkdir out
# Create client_root
try openssl genrsa -out out/client_root.key 2048
COMMON_NAME="Client Root CA" \
ID=client_root \
try openssl req \
-new \
-key out/client_root.key \
-config client-certs.cnf \
-out out/client_root.csr
COMMON_NAME="Client Root CA" \
ID=client_root \
try openssl x509 \
-req -days 3650 \
-in out/client_root.csr \
-extensions ca_cert \
-extfile client-certs.cnf \
-signkey out/client_root.key \
-out out/client_root.pem
echo 1000 > out/client_root-serial
touch out/client_root-index.txt
for i in 1 2
do
# Create client_{1,2}_ca
try openssl genrsa -out "out/client_${i}_ca.key" 2048
COMMON_NAME="Client Cert ${i} CA" \
ID="client_${i}_ca" \
try openssl req \
-new \
-key "out/client_${i}_ca.key" \
-config client-certs.cnf \
-out "out/client_${i}_ca.csr"
COMMON_NAME="Client Cert ${i} CA" \
ID=client_root \
try openssl ca \
-batch \
-extensions ca_cert \
-in "out/client_${i}_ca.csr" \
-config client-certs.cnf \
-out "out/client_${i}_ca.pem"
echo $(expr 1000 + ${i}) > "out/client_${i}_ca-serial"
touch "out/client_${i}_ca-index.txt"
# Create client_{1,2}
try openssl genrsa -out "out/client_${i}.key" 2048
COMMON_NAME="Client Cert ${i}" \
ID="client_${i}" \
try openssl req \
-new \
-key "out/client_${i}.key" \
-config client-certs.cnf \
-out "out/client_${i}.csr"
COMMON_NAME="Client Cert ${i}" \
ID="client_${i}_ca" \
try openssl ca \
-batch \
-extensions user_cert \
-in "out/client_${i}.csr" \
-config client-certs.cnf \
-out "client_${i}.pem"
try openssl pkcs8 \
-topk8 -nocrypt \
-in "out/client_${i}.key" \
-outform DER \
-out "client_${i}.pk8"
try openssl x509 \
-in "client_${i}.pem" \
-outform DER \
-out "client_${i}.der"
done
# Create additional files for client_1
try openssl rsa \
-in "out/client_1.key" \
-inform PEM \
-pubout \
-outform DER \
-out client_1_spki.der
try openssl asn1parse \
-in client_1.der \
-inform DER \
-strparse 32 \
-out client_1_issuer_dn.der
# Create signatures using client_{1,2}
for i in 1 2
do
try openssl dgst \
-sha1 \
-sign "out/client_${i}.key" \
-out "signature_client${i}_sha1_pkcs" \
data
done
try openssl rsautl \
-inkey "out/client_1.key" \
-sign \
-in data \
-pkcs \
-out signature_nohash_pkcs
# Create root, l1_interm, l{1,2}_leaf
CN=root \ CN=root \
try root_cert root try root_cert root
...@@ -31,4 +167,5 @@ CA_ID=root CN=l1_interm \ ...@@ -31,4 +167,5 @@ CA_ID=root CN=l1_interm \
CA_ID=l1_interm CN=l2_leaf \ CA_ID=l1_interm CN=l2_leaf \
try issue_cert l2_leaf leaf_cert_san_dns as_der try issue_cert l2_leaf leaf_cert_san_dns as_der
try rm -rf out try rm -rf out
Mpk[3*GJ}y{ G{ھ ᄅɀCwQv#q ;c'.0w~cTg;1,h'PgJP$s n}ñPS0}I+uŗ}6Bڮ7!0lY{x8H0Ƴ>j0zLe HaV>iH ^*A+O a]rNkJxPB钬!lay4{_( vE=&.^۩;&vjuOl'˳ĸ8~jܗ < "s}oӠzxZWX9>yg66AeI
\ No newline at end of file :}B$Y<}\*v2ޓ1{
e#/0o{I% -ffۈF9+Ypy7TkAHpMЇ[ rIӴ_A|V2O|NL<1_> 9:1IaQ,*Ҷ 6WfdF=I԰R(^
\ No newline at end of file
W{"([1A<RāG+H_\ Y(?Mi^-ezQf"@:ZfZ/QNV
Hb> h2Z뵲2I,|QRE Rɉ!Pd(a˙W]bn&KI|C!4+9J[M7 z*)3 WōZE)Ж]Nan*;x > !֌7"+<0[LT@@QL#kIYE2bV89Z#NE! | Xo W_+A9w5G8Cpd)LP 8X
!xi/WPja%Fgp:Ⱨ;\h+z 眆lBlrjtO-Tտ2 * D}xpU.J?f0}ֱ5h"v/" Ӫظ<Ԟm%F !l7|âC
\ No newline at end of file \ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment