|
1 | 1 | # Copyright (c) 2023 Apple Inc. Licensed under MIT License. |
2 | 2 |
|
3 | 3 | import unittest |
| 4 | +from unittest import mock |
| 5 | +from unittest.mock import MagicMock, patch |
4 | 6 |
|
5 | 7 | from appstoreserverlibrary.signed_data_verifier import _ChainVerifier, VerificationException, VerificationStatus |
6 | 8 | from base64 import b64decode, b64encode |
|
20 | 22 | REAL_APPLE_SIGNING_CERTIFICATE_BASE64_ENCODED = "MIIEMDCCA7agAwIBAgIQaPoPldvpSoEH0lBrjDPv9jAKBggqhkjOPQQDAzB1MUQwQgYDVQQDDDtBcHBsZSBXb3JsZHdpZGUgRGV2ZWxvcGVyIFJlbGF0aW9ucyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTELMAkGA1UECwwCRzYxEzARBgNVBAoMCkFwcGxlIEluYy4xCzAJBgNVBAYTAlVTMB4XDTIxMDgyNTAyNTAzNFoXDTIzMDkyNDAyNTAzM1owgZIxQDA+BgNVBAMMN1Byb2QgRUNDIE1hYyBBcHAgU3RvcmUgYW5kIGlUdW5lcyBTdG9yZSBSZWNlaXB0IFNpZ25pbmcxLDAqBgNVBAsMI0FwcGxlIFdvcmxkd2lkZSBEZXZlbG9wZXIgUmVsYXRpb25zMRMwEQYDVQQKDApBcHBsZSBJbmMuMQswCQYDVQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABOoTcaPcpeipNL9eQ06tCu7pUcwdCXdN8vGqaUjd58Z8tLxiUC0dBeA+euMYggh1/5iAk+FMxUFmA2a1r4aCZ8SjggIIMIICBDAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFD8vlCNR01DJmig97bB85c+lkGKZMHAGCCsGAQUFBwEBBGQwYjAtBggrBgEFBQcwAoYhaHR0cDovL2NlcnRzLmFwcGxlLmNvbS93d2RyZzYuZGVyMDEGCCsGAQUFBzABhiVodHRwOi8vb2NzcC5hcHBsZS5jb20vb2NzcDAzLXd3ZHJnNjAyMIIBHgYDVR0gBIIBFTCCAREwggENBgoqhkiG92NkBQYBMIH+MIHDBggrBgEFBQcCAjCBtgyBs1JlbGlhbmNlIG9uIHRoaXMgY2VydGlmaWNhdGUgYnkgYW55IHBhcnR5IGFzc3VtZXMgYWNjZXB0YW5jZSBvZiB0aGUgdGhlbiBhcHBsaWNhYmxlIHN0YW5kYXJkIHRlcm1zIGFuZCBjb25kaXRpb25zIG9mIHVzZSwgY2VydGlmaWNhdGUgcG9saWN5IGFuZCBjZXJ0aWZpY2F0aW9uIHByYWN0aWNlIHN0YXRlbWVudHMuMDYGCCsGAQUFBwIBFipodHRwOi8vd3d3LmFwcGxlLmNvbS9jZXJ0aWZpY2F0ZWF1dGhvcml0eS8wHQYDVR0OBBYEFCOCmMBq//1L5imvVmqX1oCYeqrMMA4GA1UdDwEB/wQEAwIHgDAQBgoqhkiG92NkBgsBBAIFADAKBggqhkjOPQQDAwNoADBlAjEAl4JB9GJHixP2nuibyU1k3wri5psGIxPME05sFKq7hQuzvbeyBu82FozzxmbzpogoAjBLSFl0dZWIYl2ejPV+Di5fBnKPu8mymBQtoE/H2bES0qAs8bNueU3CBjjh1lwnDsI=" |
21 | 23 |
|
22 | 24 | EFFECTIVE_DATE = 1681312846 |
| 25 | +CLOCK_DATE = 41231 |
23 | 26 |
|
24 | 27 | class X509Verification(unittest.TestCase): |
25 | 28 | def test_valid_chain_without_ocsp(self): |
@@ -115,6 +118,82 @@ def test_apple_chain_is_valid_with_ocsp_and_strict(self): |
115 | 118 | REAL_APPLE_ROOT_BASE64_ENCODED |
116 | 119 | ], True, EFFECTIVE_DATE) |
117 | 120 |
|
| 121 | + def test_ocsp_response_caching(self): |
| 122 | + verifier = _ChainVerifier([b64decode(REAL_APPLE_ROOT_BASE64_ENCODED)]) |
| 123 | + magic_mock = MagicMock(return_value=LEAF_CERT_BASE64_ENCODED) |
| 124 | + verifier._verify_chain_without_caching = magic_mock |
| 125 | + with patch('time.time', mock.MagicMock(return_value=CLOCK_DATE)): |
| 126 | + verifier.verify_chain([ |
| 127 | + REAL_APPLE_SIGNING_CERTIFICATE_BASE64_ENCODED, |
| 128 | + REAL_APPLE_INTERMEDIATE_BASE64_ENCODED, |
| 129 | + REAL_APPLE_ROOT_BASE64_ENCODED |
| 130 | + ], True, EFFECTIVE_DATE) |
| 131 | + self.assertEqual(1, magic_mock.call_count) |
| 132 | + with patch('time.time', mock.MagicMock(return_value=CLOCK_DATE + 1)): # 1 second |
| 133 | + verifier.verify_chain([ |
| 134 | + REAL_APPLE_SIGNING_CERTIFICATE_BASE64_ENCODED, |
| 135 | + REAL_APPLE_INTERMEDIATE_BASE64_ENCODED, |
| 136 | + REAL_APPLE_ROOT_BASE64_ENCODED |
| 137 | + ], True, EFFECTIVE_DATE) |
| 138 | + self.assertEqual(1, magic_mock.call_count) |
| 139 | + |
| 140 | + def test_ocsp_response_caching_has_expiration(self): |
| 141 | + verifier = _ChainVerifier([b64decode(REAL_APPLE_ROOT_BASE64_ENCODED)]) |
| 142 | + magic_mock = MagicMock(return_value=LEAF_CERT_BASE64_ENCODED) |
| 143 | + verifier._verify_chain_without_caching = magic_mock |
| 144 | + with patch('time.time', mock.MagicMock(return_value=CLOCK_DATE)): |
| 145 | + verifier.verify_chain([ |
| 146 | + REAL_APPLE_SIGNING_CERTIFICATE_BASE64_ENCODED, |
| 147 | + REAL_APPLE_INTERMEDIATE_BASE64_ENCODED, |
| 148 | + REAL_APPLE_ROOT_BASE64_ENCODED |
| 149 | + ], True, EFFECTIVE_DATE) |
| 150 | + self.assertEqual(1, magic_mock.call_count) |
| 151 | + with patch('time.time', mock.MagicMock(return_value=CLOCK_DATE + 900)): # 15 minutes |
| 152 | + verifier.verify_chain([ |
| 153 | + REAL_APPLE_SIGNING_CERTIFICATE_BASE64_ENCODED, |
| 154 | + REAL_APPLE_INTERMEDIATE_BASE64_ENCODED, |
| 155 | + REAL_APPLE_ROOT_BASE64_ENCODED |
| 156 | + ], True, EFFECTIVE_DATE) |
| 157 | + self.assertEqual(2, magic_mock.call_count) |
| 158 | + |
| 159 | + def test_ocsp_response_caching_with_different_chain(self): |
| 160 | + verifier = _ChainVerifier([b64decode(REAL_APPLE_ROOT_BASE64_ENCODED)]) |
| 161 | + magic_mock = MagicMock(return_value=LEAF_CERT_BASE64_ENCODED) |
| 162 | + verifier._verify_chain_without_caching = magic_mock |
| 163 | + with patch('time.time', mock.MagicMock(return_value=CLOCK_DATE)): |
| 164 | + verifier.verify_chain([ |
| 165 | + LEAF_CERT_BASE64_ENCODED, |
| 166 | + INTERMEDIATE_CA_BASE64_ENCODED, |
| 167 | + ROOT_CA_BASE64_ENCODED |
| 168 | + ], True, EFFECTIVE_DATE) |
| 169 | + self.assertEqual(1, magic_mock.call_count) |
| 170 | + with patch('time.time', mock.MagicMock(return_value=CLOCK_DATE)): # Same |
| 171 | + verifier.verify_chain([ |
| 172 | + REAL_APPLE_SIGNING_CERTIFICATE_BASE64_ENCODED, |
| 173 | + REAL_APPLE_INTERMEDIATE_BASE64_ENCODED, |
| 174 | + REAL_APPLE_ROOT_BASE64_ENCODED |
| 175 | + ], True, EFFECTIVE_DATE) |
| 176 | + self.assertEqual(2, magic_mock.call_count) |
| 177 | + |
| 178 | + def test_ocsp_response_caching_with_slightly_different_chain(self): |
| 179 | + verifier = _ChainVerifier([b64decode(REAL_APPLE_ROOT_BASE64_ENCODED)]) |
| 180 | + magic_mock = MagicMock(return_value=LEAF_CERT_BASE64_ENCODED) |
| 181 | + verifier._verify_chain_without_caching = magic_mock |
| 182 | + with patch('time.time', mock.MagicMock(return_value=CLOCK_DATE)): |
| 183 | + verifier.verify_chain([ |
| 184 | + LEAF_CERT_BASE64_ENCODED, |
| 185 | + INTERMEDIATE_CA_BASE64_ENCODED, |
| 186 | + ROOT_CA_BASE64_ENCODED |
| 187 | + ], True, EFFECTIVE_DATE) |
| 188 | + self.assertEqual(1, magic_mock.call_count) |
| 189 | + with patch('time.time', mock.MagicMock(return_value=CLOCK_DATE)): # Same |
| 190 | + verifier.verify_chain([ |
| 191 | + LEAF_CERT_BASE64_ENCODED, |
| 192 | + INTERMEDIATE_CA_BASE64_ENCODED, |
| 193 | + REAL_APPLE_ROOT_BASE64_ENCODED |
| 194 | + ], True, EFFECTIVE_DATE) |
| 195 | + self.assertEqual(2, magic_mock.call_count) |
| 196 | + |
118 | 197 |
|
119 | 198 | if __name__ == '__main__': |
120 | 199 | unittest.main() |
0 commit comments