1 # Copyright (c) 2013 The Chromium OS Authors. All rights reserved. 2 # Use of this source code is governed by a BSD-style license that can be 3 # found in the LICENSE file. 4 5 import base64 6 import json 7 import logging 8 import os.path 9 import tempfile 10 11 import common 12 from autotest_lib.client.bin import test 13 from autotest_lib.client.common_lib import error 14 from autotest_lib.client.common_lib import utils 15 16 # This modifies the include path to include the shill test-scripts. 17 # pylint: disable=W0611 18 from autotest_lib.client.cros import flimflam_test_path 19 # pylint: enable=W0611 20 import crypto_util_pb2 21 22 23 TEST_DATA1 = """{ 24 "connected":false, 25 "debug_build":true, 26 "has_update":false, 27 "hotspot_bssid":"00:1A:11:FF:AC:DF", 28 "locale":"en_US", 29 "location": { 30 "latitude":37.4193105, 31 "longitude":-122.07878869999999 32 }, 33 "mac_address":"4C:AA:16:A5:AC:DF", 34 "name":"eureka8997", 35 "public_key":"MIGJAoGBAK3SXmWZBOhJibv8It05qIbgHXXhnCXxHkW+C6jNMHR5sZgDpFaOY1xwXERjKdJxcwrEy3VAT5Uv9MgHPBvxxJku76HYh1yVfIw1rhLnHBTHSxwUzJNCrgc3l3t/UACacLjVNIzccDpYf2vnOcA+t1t6IXRjzuU2NdwY4dJXNtWPAgMBAAE=", 36 "setup_state":11, 37 "sign": { 38 "certificate":"-----BEGIN CERTIFICATE-----\\nMIIDhzCCAm8CBFE2SCMwDQYJKoZIhvcNAQEFBQAwfTELMAkGA1UEBhMCVVMxEzAR\\nBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxEzARBgNV\\nBAoMCkdvb2dsZSBJbmMxEjAQBgNVBAsMCUdvb2dsZSBUVjEYMBYGA1UEAwwPRXVy\\nZWthIEdlbjEgSUNBMB4XDTEzMDMwNTE5MzE0N1oXDTMzMDIyODE5MzE0N1owgYMx\\nFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxEjAQBgNVBAsTCUdvb2dsZSBUVjETMBEG\\nA1UEChMKR29vZ2xlIEluYzETMBEGA1UECBMKQ2FsaWZvcm5pYTELMAkGA1UEBhMC\\nVVMxHjAcBgNVBAMUFWV2dF9lMTYxIDAwMWExMWZmYWNkZjCCASIwDQYJKoZIhvcN\\nAQEBBQADggEPADCCAQoCggEBAPHGDV0lLoTYK78q13y/2u77YTjgbBlWAOxgrSNc\\nMmGHx1K0aPyo50p99dGQnjapW6jtGrMzReWV2Wz3VL8rYlqY7oWjeJwsLQwo2tcn\\n7vIZ/PuvPz9xgnGMUbBOfhCf3Epb1N4Jz82pxxrOFhUawWAglC9C4fUeZLCZpOJs\\nQd4QeAznkydl3xbqdSm74kwxE6vkGEzSCDnC7aYx0Rvvr1mZOKdl4AinYrxzWgmV\\nsTnaFT1soSjmC5e/i6Jcrs4dDFgY6mKy9Qtly2XPSCYljm6L4SgqgJNmlpY0qYJg\\nO++BdofIbU2jsOiCMvIuKkbMn72NsPQG0QhnVMwk7kYg6kkCAwEAAaMNMAswCQYD\\nVR0TBAIwADANBgkqhkiG9w0BAQUFAAOCAQEAW0bQl9yjBc7DgMp94i7ZDOUxKQrz\\nthephuwzb3/wWiTHcw6KK6FRPefXn6NPWxKKeQmv/tBxHbVlmYRXUbrhksnD0aUk\\ni4InvtL2m0H1fPfMxmJRFE+HoSXu+s0sGON831JaMcYRbAku5uHnltaGNzOI0KPH\\nFGoCDmjAZD+IuoR2LR4FuuTrECK7KLjkdf//z5d5j7nBDPZS7uTCwC/BwM9asRj3\\ntJA5VRFbLbsit1VI7IaRCk9rsSKkpBUaVeKbPLz+y/Z6JonXXT6AxsfgUSKDd4B7\\nMYLrTwMQfGuUaaaKko6ldKIrovjrcPloQr1Hxb2bipFcjLmG7nxQLoS6vQ==\\n-----END CERTIFICATE-----\\n", 39 "nonce":"+6KSGuRu833m1+TP", 40 "signed_data":"vwMBgANrp5XpCswLyk/OTXT56ORPeIWjH7xAdCk3qgjkwI6+8o56zJS02+tC5hhIHWh7oppTmWYF4tKvBQ3GeCz7IW9f7HWDMtO7x7yRWxzJyehaJbCfXvLdfs0/WKllzvGVBgNpcIAwU2NSFUG/jpXclntFzds0EUJG9wHxS6PXXSYRu+PlIFdCDcQJsUlnwO9AGFOJRV/aARGh8YUTWCFIQPOtPEqT5eegt+TLf01Gq0YcrRwSTKy1I3twOnWiMfIdkJdQKPtBwwbvuAyGuqYFocfjKABbnH9Tvl04yyO3euKbYlSqaF/l8CXmzDJTyO7tDOFK59bV9auE4KljrQ==" 41 }, 42 "ssdp_udn":"c5b2a83b-5958-7ce6-b179-e1f44699429b", 43 "ssid":"", 44 "timezone":"America/Los_Angeles", 45 "uptime":1991.7, 46 "version":4, 47 "wpa_configured":false, 48 "wpa_state":1 49 } """ 50 TEST_DATA2 = """{ 51 "connected": false, 52 "debug_build": true, 53 "has_update": false, 54 "hotspot_bssid": "00:1A:11:FF:AC:1E", 55 "ip_address": "192.168.43.32", 56 "locale": "en_US", 57 "mac_address": "B0:EE:45:49:AC:1E", 58 "name": "Greg's Eureka", 59 "noise_level": -85, 60 "public_key": "MIGJAoGBAOe+6bF51A7wFVMbyPiHYLdgAmP6sdhOUohqCHn4qHSfDY41AbAbVmXLbUZ5BF2KSdDYqU4fAXoaI8V8D5DRWh57Ax10Sl1/6M1u22KT6FYQyUToXGPcXldBzRRMok8H4XyiebDVevjvvV6yuABSYYhfSlrMdGj8qxRVwTxx0CItAgMBAAE=", 61 "release_track": "beta-channel", 62 "setup_state": 50, 63 "sign": { 64 "certificate": "-----BEGIN CERTIFICATE-----\\nMIIDejCCAmICBFEtN4wwDQYJKoZIhvcNAQEFBQAwfTELMAkGA1UEBhMCVVMxEzAR\\nBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxEzARBgNV\\nBAoMCkdvb2dsZSBJbmMxEjAQBgNVBAsMCUdvb2dsZSBUVjEYMBYGA1UEAwwPRXVy\\nZWthIEdlbjEgSUNBMB4XDTEzMDIyNjIyMzAzNloXDTMzMDIyMTIyMzAzNlowdzET\\nMBEGA1UECBMKQ2FsaWZvcm5pYTELMAkGA1UEBhMCVVMxFjAUBgNVBAcTDU1vdW50\\nYWluIFZpZXcxEjAQBgNVBAsTCUdvb2dsZSBUVjETMBEGA1UEChMKR29vZ2xlIElu\\nYzESMBAGA1UEAxQJZXZ0X2UxMjYyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\\nCgKCAQEAo7Uu+bdyCjtiUYpmNU4ZvRjDg6VkEh/g0YPDG2pICBU4XKvsqHH1i0hb\\ntWp1J79hV9Rqst1yHT02Oeh3o1SOd2zeamYzmvXRVN7AZqfQlzWxwxk/ltpXGwew\\nm+EIR2bP4kpvyEKvvziTMtTxviOK+A395QyodMhMXClKTus/Gme2r1fBoQqJJR/z\\nrmwXCsl5kpdhj7FOIII3BCYV0zejjQquzywjsKfCVON28VGgJdaKgmXxkeRYYWVN\\nnuTNna57vXe16FP6hS1ty1U77ESffLTpNJ/M4tsd2dMVVTDuGeX3q8Ix4TN8cqpq\\nu1AKEf59hygys9j6cHZRKR/div0+uQIDAQABow0wCzAJBgNVHRMEAjAAMA0GCSqG\\nSIb3DQEBBQUAA4IBAQAZx6XyEK9SLHE+rbKCVsLN9+hTEa50aikPmxOZt+lFuB4+\\nVJZ/GCPQCZJIde2tlWUe2YBgoZw2xUKgIsM3Yq42Gawi35/oZ3qycTgYU8KJP9kU\\nMbYNAH90mz9BDH7MmnRID5dFexHyBCG88EJ+ZvxmUVn0EVDcsSMt11wIAZ/T+/gs\\nE1120d/GxhjYQ9YZz7SZXBQfRdqCdcPNl2+QSHHl+WvYLzdJa2xYj39/kQu47Vp7\\nX5rZrHSBvzdVymH0Od2D18t+Q6lxbSdyUNhP1MVhdkT1Ct4OmRS3FJ4aannXMhfq\\nNg7k4Sfif5iktYT4VRKpThe0EGJNfqKJKYtvHEVC\\n-----END CERTIFICATE-----\\n", 65 "nonce": "pTwRhdsB5cb3Ev8o", 66 "signed_data": "WIvN6Ujo4CoxUNcsm1YaLRUe1KJVEG+oXorUBJae/fKQrLfnH9ChDfxzW+EDZlLBLPk9u5EAptr8LKK6AunbBTDIeBkjzXv3nS+xlmV9ZdA71imitva88HPzC+a2H61dJL8puNbZu9j1Zs3sCybw2F+qZbDBhbG0sJTEXytPjewqAl8iBZSAS0BoNJZYA7Q/bCPI07pg404pI392cKP8FYJR08Y4xoV94Em+jnZ2nZabSsmsScYGvpWVNeS2z+f0to6ureOxaqgT+AAckqtCRcHd66QtLGwKXWviaevKte1z185f4r55U4P5pkQi+xd6lZRsMQydwUzLxgk7UY5U3Q==" 67 }, 68 "signal_level": -42, 69 "ssdp_udn": "cd7c1f15-2f49-076b-51ac-9d651872c784", 70 "ssid": "Greg's Phone", 71 "timezone": "America/Los_Angeles", 72 "uptime": 207.33, 73 "version": 4, 74 "wpa_configured": true, 75 "wpa_id": 0, 76 "wpa_state": 10 77 } 78 """ 79 TEST_DATA3 = """{ 80 "build_version":"10566", 81 "connected":false, 82 "has_update":false, 83 "hotspot_bssid":"FA:8F:CA:30:08:26", 84 "locale":"en_US", 85 "mac_address":"B0:EE:45:68:B5:52", 86 "name":"Chromekey Greg", 87 "public_key":"MIIBCgKCAQEApQoxFRJWEP9Oa+lSF2PCMBCpd2LYeyPMHjVKCF2IlrGbrgQ3U9wI6tBvLkHg570KSA6onL/7e9J31RLwA8gIE0zJ9M7NToxj1cVa8jOqXPIllJP7uY/TmtMIwCvuMCu6KBNW/wzKK6jkT7wScwrPJscmwWr/0h6lKXZrv0DhwvVv3i6VGsasZzVYlOoZ7eRe1OHiJgehPFUh0Vp7lVRDzumtJ0N6hybWP/Ap6dNlcO9Hq67bljHRrgwuBT2iRJBIdZt6m4xZlf78dH6Y2gfeQ3GBtDZWbZ5v6hzaYeIxlMTelz6ZlEQa0fPegK1dsxCddvLhRCDQr2bZlwyRdof6uwIDAQAB", 88 "release_track":"beta-channel", 89 "setup_state":11, 90 "sign": { 91 "certificate": "-----BEGIN CERTIFICATE-----\\nMIIDpjCCAo4CBFFfTz8wDQYJKoZIhvcNAQEFBQAwfTELMAkGA1UEBhMCVVMxEzAR\\nBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxEzARBgNV\\nBAoMCkdvb2dsZSBJbmMxEjAQBgNVBAsMCUdvb2dsZSBUVjEYMBYGA1UEAwwPRXVy\\nZWthIEdlbjEgSUNBMB4XDTEzMDQwNTIyMjUwM1oXDTMzMDMzMTIyMjUwM1owgYAx\\nCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRMwEQYDVQQKEwpHb29n\\nbGUgSW5jMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRIwEAYDVQQLEwlHb29nbGUg\\nVFYxGzAZBgNVBAMTElpaQUlNIEZBOEZDQTMwMDgyNjCCASIwDQYJKoZIhvcNAQEB\\nBQADggEPADCCAQoCggEBALmAGRcIQt/k7WfoUHDCWQhzQ/FrHDnNiHcVj09Tyu7/\\n2pIB+pVnLac8pfFwdVAcDG4xmjnROIHeajz627uq8bHEVDfPCHe8WiM+CsPrMC85\\nlQOq8rBwNw3WO82suvWL8wjdqFy0uQHajp9e9ix3FXzfZDAuf7ABHmVZnPMWQz0a\\nR3zDCCF2NhEVhBwq+IGKNNvuIPhVF/5tkdWPmihFukJabmV2kjFUuPbEf4T1OMu+\\nhyqZ+lsTc/XVIqICRIq9ZE36MquAw0g9Hoah8OFFpkq2xJqlCY+HKvdhiA1HybfY\\nXSxOsI2rTQk3YHFMrAGMu16UYuOA+CRHD+UC8SI0fqkCAwEAAaMvMC0wCQYDVR0T\\nBAIwADALBgNVHQ8EBAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcN\\nAQEFBQADggEBAJGyWBoDvwZBlDcyX31l5kwGVf6nVZR4KedcQMGpm76C6fgzeLHt\\nAq7OQhZgifFVLvzG7kqYgRRsW7WQKTF/QmHn8rnCdY16YtZv3vFzLbdBWkmSqAxD\\nqmBum9oD74AYeJaR0v68KCGvAVG0juRSs3H93s8k/fhY+LespUMlHwB4DwRYxDNP\\nIu3HX8NEmOBwjodKDDa8yu1weYUf8GFXH3b+tu7IHRzQpPzbSSibs+AXc8WbJWk3\\nrtQSugqegiiM/OAdRuSvkXtc1DJP9F7OLsVpF9i/VZ2k/QDPCu06vXB2w3wlRyR3\\nf6nQGB1Ej8Klsxlo8B+rmQ6N8C7f48GMI8s=\\n-----END CERTIFICATE-----\\n", 92 "nonce": "E1oqNODwWVIfSjUs", 93 "signed_data": "aaT56/P7KiMxVbWCedpSNIikpxh0EzdjgEuP153pCNfYys2KmlVtvEnXeFGYKJP2ypsX0qx/9Bx2C18T8HZ4PvNW0fUEheScvkzbDTn/gBpwUJv3XT+55XneUdjIAQu83qNR/AjxYa9cDGzxbnZJL91Fd1Grw/fNaKEMiedWRiESABQREiS2OW+iZ3Z/JRs99o4M6m+6f/mvNkgZ3GrFxNnPEXe7g1sYjspPhnDLvASNzd9j24YIxu+PTWZCNL6clps+/ghNA/0fB3PBDILrcGnER36Vc8gNhjD1r1f/ACU1qk06yMNC/Kgt2pMQkpjaXby+B75Z9yrogNHs4f5tIA==" 94 }, 95 "ssdp_udn":"b91027b5-f19e-7df6-6533-5056ad190575", 96 "ssid":"Greg's Phone", 97 "uptime":262650.75, 98 "version":4, 99 "wpa_configured":false, 100 "wpa_id":0, 101 "wpa_state":1 102 }""" 103 # This is just a DER formatted public key with the first 22 bytes stripped. 104 # Technically, this is called RSAPublicKey format. 105 ENCRYPTION_PUBLIC_KEY = ( 106 '0\x81\x89\x02\x81\x81\x00\xd4\xe3z\x82\x0b6D\x8a\x1dY' 107 '\x1d\xdel\xbf\xad,\r\x8b\xefm\xe3\xbd\xef<\x954\x96C<' 108 '\x9e\x7fB\xef\xe8&h\xfb\xc4Z\x0e\x196C\x1d\xd7f\x88\\5' 109 '\xd5\x1e\xb8\xe0\x8d\xc4\xbc\xd1\xb3\xc4\xd3)!7\xd2{' 110 '\x11\x89\t\xfb\x8d\xe8\xbaRL\xacI\xf2\x0f.JB\x8e\xd4' 111 '\xdc\xc2\x81v6\x8a\x154\xbe8\xfc\xa8\x84zH\xf0j\x87(' 112 '\xcf\x142B\xcfV\xd0\n\xbbPW\x80d\xd2\x0e\xf1\x1a\x04' 113 '\x0b\xa8U=\x8f3\x85\xcd\x02\x03\x01\x00\x01' 114 ) 115 # This is the matching private key. Note that the public key is 116 # a subset of this information should you need it for debugging. 117 ENCRYPTION_PRIVATE_KEY = """ 118 -----BEGIN RSA PRIVATE KEY----- 119 MIICXQIBAAKBgQDU43qCCzZEih1ZHd5sv60sDYvvbeO97zyVNJZDPJ5/Qu/oJmj7 120 xFoOGTZDHddmiFw11R644I3EvNGzxNMpITfSexGJCfuN6LpSTKxJ8g8uSkKO1NzC 121 gXY2ihU0vjj8qIR6SPBqhyjPFDJCz1bQCrtQV4Bk0g7xGgQLqFU9jzOFzQIDAQAB 122 AoGBALfdR/9s44/KoZJIQ8Q0v8HeaU9+30U5jF9pLaYggtty2nTsR5u6d/TZPY42 123 BcVeXBV6XbBa8NZMJelXQvCw6d3hrirtRgqo+R9n6Z5Ji9oKA9NR0ZD0d66OLgRz 124 7U1w2wiM9KqfjRpRhuID1MrDF8R0mxORSFnlMeoHD74ncK6ZAkEA+NBV2OOigyU/ 125 CVWCTKmOpxUGb6bRZfvQRln4XlVUhSgZU0Acf0APl3Av1vUPyPjRIXRnMS5ZBDFK 126 YoUqWH3ymwJBANsJhX3HHYXk7aDrmPKE7q25xR7Eu4C7XEdiG0SSl8PNAicU0APy 127 zFs9GLhTgGCTZf/SCzH6ejEIiOC/RZeqW7cCQCapAF3F6O9lryi9H5TX17GAY9Kf 128 YfPtr4vu2NeXfJ2AAIdd88+V3ZZTOSu2QjCg8KW5F3udzvkGy58JP+4mC7cCQBEU 129 +gMoHyZNBzcwiHoJYe/MeBIBN7o/Yl/yx7ueTxWnDE7t8ZcNPWC0MBRX9sARXrgH 130 snXQWe0vBDW61PuR/psCQQDthOoMBnuWamOEZrEJr+itK5+ZPlE+KpT3ladXui57 131 zvz3CljmlLwyufahWaF+LzfohVAG5CLr4Zi/bv7j1lnJ 132 -----END RSA PRIVATE KEY----- 133 """ 134 135 136 def unicode2str(value): 137 """ 138 Recurses through value, converting unicode to strings. 139 140 The output of the json python decoder looks like a dictionary with 141 unicode keys mapping to more unicode strings, and possibly 142 dictionaries. Convert those unicode strings to ASCII strings 143 recursively with this function. 144 145 @param value: dict or unicode. 146 @returns value with unicode recursively replaced with string. 147 148 """ 149 if isinstance(value, dict): 150 ret = {} 151 for k,v in value.items(): 152 ret[unicode2str(k)] = unicode2str(v) 153 return ret 154 155 if isinstance(value, unicode): 156 return str(value) 157 158 return value 159 160 161 class network_DestinationVerification(test.test): 162 """Tests that the destination verification logic in shill works. 163 164 This logic allows us to verify that (for instance) we trust the 165 credentials of a Chromekey. 166 167 """ 168 version = 1 169 170 171 @property 172 def shim_path(self): 173 """@return path to crypto-util shim.""" 174 lib_paths = ['lib', 'lib64'] 175 shim_path = '/usr/%s/shill/shims/crypto-util' 176 for lib in lib_paths: 177 path = shim_path % lib 178 if os.path.exists(path): 179 return path 180 raise error.TestFail('Unable to find crypto-util.') 181 182 183 def _call_shim_with_args(self, args, protobuffer): 184 """Calls the crypto_util shim with args and stdin as specified. 185 186 Calls crypto shim with args for paramters, and the serialized form of 187 protobuffer on stdin. Asserts that the command completes successfully 188 and returns the raw output bytestring. 189 190 @param args: tuple of string arguments to the shim. 191 @param protobuffer: python protocol buffer object. 192 @return stdout of the shim call as string. 193 194 """ 195 raw_input_bytes = protobuffer.SerializeToString() 196 result = utils.run(self.shim_path, 197 stderr_tee=utils.TEE_TO_LOGS, 198 stdin=raw_input_bytes, 199 verbose=True, 200 args=args, 201 timeout=10, 202 ignore_status=True) 203 if result.exit_status: 204 return None 205 raw_output = result.stdout 206 logging.debug('Got raw output: %s.', 207 ''.join([hex(ord(c)) for c in raw_output])) 208 return raw_output 209 210 211 def _test_verify(self, test_data, expect_failure=False): 212 """Test that shim verify operation works correctly. 213 214 Call into the shim to perform a verify operation, check that the call 215 succeeds unless |expect_failure|. |test_data| looks like the decoded 216 json data we're given by the destination. 217 218 @param test_data: dictionary of test data to use with the call. 219 @param expect_failure: bool true if test_data should fail to verify. 220 221 @raises TestFail when verification doesn't go as expected. 222 223 """ 224 # See doc/manager-api.txt, but the format goes roughly: 225 # ssid,udn,bssid,key,nonce 226 sign_bundle = test_data['sign'] 227 unsigned_data = '%s,%s,%s,%s,%s' % (test_data['name'], 228 test_data['ssdp_udn'], 229 test_data['hotspot_bssid'], 230 test_data['public_key'], 231 sign_bundle['nonce']) 232 message = crypto_util_pb2.VerifyCredentialsMessage() 233 message.certificate = sign_bundle['certificate'] 234 message.signed_data = base64.b64decode(sign_bundle['signed_data']) 235 message.unsigned_data = unsigned_data 236 message.mac_address = test_data['hotspot_bssid'] 237 output = self._call_shim_with_args(('verify',), message) 238 if expect_failure: 239 if output is None: 240 # Expected a failure, and got it. We're done here. 241 return 242 raise error.TestFail('Expected verification to fail, but it ' 243 'succeeded.') 244 245 if not output: 246 raise error.TestFail('Verification failed unexpectedly.') 247 248 response = crypto_util_pb2.VerifyCredentialsResponse() 249 response.ParseFromString(output) 250 if response.ret != crypto_util_pb2.OK: 251 raise error.TestFail('Expected verification success, ' 252 'but got: %d.' % response.ret) 253 254 255 def _test_encrypt(self, public_key, data_to_encrypt, expect_failure=False): 256 """Test that shim encrypt operation works correctly. 257 258 Call into the shim to perform an encrypt operation. 259 Raise a test error if the call fails, unless |expect_failure|. 260 261 @param public_key: string containing RSAPublicKey format RSA key. 262 @param data_to_encrypt: string data to encrypt. 263 @param expect_failure: bool true if encrypt should fail. 264 265 """ 266 message = crypto_util_pb2.EncryptDataMessage() 267 message.public_key = public_key 268 message.data = data_to_encrypt 269 output = self._call_shim_with_args(('encrypt',), message) 270 if expect_failure: 271 if output is None: 272 # Expected a failure, and got it. We're done here. 273 return 274 raise error.TestFail('Expected encryption to fail, ' 275 'but it did not.') 276 277 if not output: 278 raise error.TestFail('Encryption failed unexpectedly.') 279 280 response = crypto_util_pb2.EncryptDataResponse() 281 response.ParseFromString(output) 282 if response.ret != crypto_util_pb2.OK: 283 raise error.TestFail('Data encryption failed.') 284 285 logging.debug('Decrypting %d bytes of encrypted data to confirm match.', 286 len(response.encrypted_data)) 287 try: 288 private_key = tempfile.NamedTemporaryFile() 289 encrypted_data = tempfile.NamedTemporaryFile() 290 private_key.write(ENCRYPTION_PRIVATE_KEY) 291 private_key.flush() 292 encrypted_data.write(response.encrypted_data) 293 encrypted_data.flush() 294 result = utils.run('openssl rsautl -decrypt -inkey %s -in %s' % 295 (private_key.name, encrypted_data.name), 296 stdin=response.encrypted_data, 297 stderr_tee=utils.TEE_TO_LOGS, 298 verbose=True, 299 ignore_status=True) 300 if result.exit_status: 301 if data_to_encrypt == '': 302 # Due to an open bug in OpenSSL, rsautl doesn't handle this 303 # case correctly. For now, just pass and assume that 304 # we're doing this correctly. 305 # http://rt.openssl.org/Ticket/Display.html?id=2018 306 return 307 raise error.TestFail('Failed to decrypt shim output.') 308 309 if result.stdout != data_to_encrypt: 310 raise error.TestFail('Data encyption failed: ' 311 'expected: %s, but got: %s' % 312 (data_to_encrypt, result.stdout)) 313 314 finally: 315 private_key.close() 316 encrypted_data.close() 317 318 319 def run_once(self): 320 """Body of the test.""" 321 logging.info('Checking basic encryption operation of the shim.') 322 self._test_encrypt(ENCRYPTION_PUBLIC_KEY, 'disco boy') 323 324 logging.info('Checking graceful fail for too much data to encrypt.') 325 self._test_encrypt(ENCRYPTION_PUBLIC_KEY, 326 ''.join(['x' for i in range(500)]), 327 expect_failure=True) 328 329 logging.info('Checking graceful fail for a bad key format.') 330 self._test_encrypt('this will not parse in openssl', 331 'disco boy', 332 expect_failure=True) 333 334 logging.info('Checking that we encrypt the empty string correctly.') 335 self._test_encrypt(ENCRYPTION_PUBLIC_KEY, '') 336 337 logging.info('Checking basic verification operation.') 338 test_data = unicode2str(json.loads(TEST_DATA1)) 339 self._test_verify(test_data) 340 341 logging.info('Checking bad nonce in unsigned_data.') 342 test_data = unicode2str(json.loads(TEST_DATA1)) 343 test_data['sign']['nonce'] = 'does not match' 344 self._test_verify(test_data, expect_failure=True) 345 346 logging.info('Checking for graceful fail for invalid ' 347 'certificate format') 348 test_data = unicode2str(json.loads(TEST_DATA1)) 349 test_data['sign']['certificate'] = 'not a certificate' 350 self._test_verify(test_data, expect_failure=True) 351 352 logging.info('Verification fails when the certificate is signed, but ' 353 'subject is malformed.') 354 test_data = unicode2str(json.loads(TEST_DATA2)) 355 self._test_verify(test_data, expect_failure=True) 356 357 logging.info('Verification should succeed on third set of data.') 358 test_data = unicode2str(json.loads(TEST_DATA3)) 359 self._test_verify(test_data) 360 361 logging.info('Test completed successfully.') 362