# HG changeset patch # User Andre Heinecke # Date 1403521474 -7200 # Node ID facb13c578f10fbaf083483d437fd10a2e31e1e1 # Parent f595fcbe3e762404e8ff287c4d5203c47e6b8328 Add certificate pinning to verify_binary_win diff -r f595fcbe3e76 -r facb13c578f1 common/binverify.c --- a/common/binverify.c Fri Jun 20 14:29:05 2014 +0200 +++ b/common/binverify.c Mon Jun 23 13:04:34 2014 +0200 @@ -11,6 +11,12 @@ #include "strhelp.h" #include "logging.h" +#ifdef RELEASE_BUILD +#include "pubkey-release.h" +#else +#include "pubkey-test.h" +#endif + bin_verify_result verify_binary(const char *filename, size_t name_len) { #ifdef WIN32 @@ -25,11 +31,74 @@ #ifdef WIN32 +#include + #include #include #include #include + +/** @brief Check if the certificate @a pCCertContext is pinned + * + * Compares the certificate's binary data (public key and attributes) + * with each other to validate that the certificate pCCertContext has + * exactly the same data as the builtin public certificate. + * + * @param[in] pCCertContext pointer to the certificate to check + * + * @returns true if the certificate matches, false otherwise. + */ +static bool +check_certificate (PCCERT_CONTEXT pCCertContext) +{ + x509_crt codesign_cert; + int ret = 0; + DWORD dwI = 0; + bool retval = false; + + if (pCCertContext == NULL) + { + ERRORPRINTF ("Invalid call to check_certificate"); + return false; + } + + x509_crt_init(&codesign_cert); + + /* Parse the pinned certificate */ + ret = x509_crt_parse(&codesign_cert, + public_key_codesign_pem, + public_key_codesign_pem_size); + if (ret != 0) + { + ERRORPRINTF ("x509_crt_parse failed with -0x%04x\n\n", -ret); + goto done; + } + + if (codesign_cert.raw.len != pCCertContext->cbCertEncoded || + codesign_cert.raw.len <= 0) + { + ERRORPRINTF ("Certificate size mismatch"); + goto done; + } + + /* Check that the certificate is exactly the same as the pinned one */ + for (dwI = 0; dwI < pCCertContext->cbCertEncoded; dwI++) + { + if (pCCertContext->pbCertEncoded[dwI] != codesign_cert.raw.p[dwI]) + { + ERRORPRINTF ("Certificate content mismatch"); + goto done; + } + } + + retval = true; + +done: + x509_crt_free(&codesign_cert); + return retval; +} + bin_verify_result verify_binary_win(const char *filename, size_t name_len) { bin_verify_result retval = VerifyUnknownError; @@ -111,17 +180,29 @@ } /* Verify that the signature is actually valid */ - if(CryptMsgControl(hMsg, - 0, - CMSG_CTRL_VERIFY_SIGNATURE, - pSignerCertContext->pCertInfo)) + if(!CryptMsgControl(hMsg, + 0, + CMSG_CTRL_VERIFY_SIGNATURE, + pSignerCertContext->pCertInfo)) { - DEBUGPRINTF ("Verify signature succeeded. \n"); - /* TODO pinning*/ + ERRORPRINTF ("The signature is invalid. \n"); + retval = VerifyInvalidSignature; + syslog_error_printf ("Software update embedded signature is invalid."); + goto done; + } + + if(check_certificate(pSignerCertContext)) + { + DEBUGPRINTF ("Valid signature with pinned certificate."); retval = VerifyValid; - } else { - ERRORPRINTF ("The signature was not verified. \n"); + goto done; + } + else + { + ERRORPRINTF ("Certificate mismatch. \n"); retval = VerifyInvalidSignature; + syslog_error_printf ("Software update embedded signature " + "created with wrong certificate."); goto done; } diff -r f595fcbe3e76 -r facb13c578f1 common/binverify.h --- a/common/binverify.h Fri Jun 20 14:29:05 2014 +0200 +++ b/common/binverify.h Mon Jun 23 13:04:34 2014 +0200 @@ -26,6 +26,7 @@ VerifyValid = 100, /*! Could be read and signature matched */ VerifyUnknownError = 1, /*! The expected unexpected */ VerifyInvalidSignature = 4, /*! Signature was invalid */ + VerifyInvalidCertificate = 5, /*! Certificate mismatch */ VerifyReadFailed = 6, /*! File exists but could not read the file */ } bin_verify_result; diff -r f595fcbe3e76 -r facb13c578f1 common/pubkey-test.h --- a/common/pubkey-test.h Fri Jun 20 14:29:05 2014 +0200 +++ b/common/pubkey-test.h Mon Jun 23 13:04:34 2014 +0200 @@ -23,4 +23,43 @@ "-----END PUBLIC KEY-----\n"; static const size_t public_key_pem_size = 625; + +/* Key used for codesigning */ +static const unsigned char public_key_codesign_pem[] = +"-----BEGIN CERTIFICATE-----\n" +"MIIFqTCCA5GgAwIBAgIBATANBgkqhkiG9w0BAQUFADBZMSAwHgYDVQQDExdQdWJs\n" +"aWMgVHJ1c3RCcmlkZ2UgVGVzdDEoMCYGA1UEChMfUHVibGljIHNlY3JldCBkbyBu\n" +"b3QgdHJ1c3QgdGhpczELMAkGA1UEBhMCREUwHhcNMTMwMTAxMDAwMDAwWhcNMTUx\n" +"MjMxMjM1OTU5WjBlMSwwKgYDVQQDEyNQdWJsaWMgVHJ1c3RCcmlkZ2UgY29kZXNp\n" +"Z25pbmcgdGVzdDEoMCYGA1UEChMfUHVibGljIHNlY3JldCBkbyBub3QgdHJ1c3Qg\n" +"dGhpczELMAkGA1UEBhMCREUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC\n" +"AQDIz9IetAtdqJJ7aSfJcLmA9Mb4nxrqEJ5E6PMejDJZmmHNjyhCVp1qsLYmyC60\n" +"m7qJ4OBENx0v2n5LiCUHJpJ4mzAklkWn1GffUkzWgQ2VHw5Nr44NWEwkUUa5/jT7\n" +"Sxts2DWuaLz2r7oi6BUQpoRmQRPwwzFPONcCSw9iAvTU6oVI2jW1opEW3t10UwY3\n" +"5/muryPsUz6y5VkBIc73VC0wByXoAruEPBBpMgOVw1+npOaJ1PL1XXQ/P6xziZo0\n" +"Ab/tKvN6IpEHrNEGv1gScJt//pKKklvIyXm9UdIY9XpB6aauzthKpTFJXGYySlXx\n" +"bD1a5sq0i2sAK/p8RvErVWg3EfBlUrQryJxONPVqribczZIWcgKVEFfXjX1tQqiC\n" +"qRCgO4M6zhNIKLkAicp0DvYs8M4hIoPng98nqK6kSpfXR6Y4b9DU3yEktH7wGrwL\n" +"jKATVM2l2yTF17Pjxkr2tH0XWrChfS+oV6Qzm9JQ/vmLKz5piLKpt5SXuZny+j0Y\n" +"68ch709sVTuuPm4RAm5c5t0SCwEippClFpkZynYRsJVrjG9ZTrdvULxZao8GBzJx\n" +"Lb+tCaKP60BRoUuRfwGMKZbU6j6ujOCy5bZIoJaKgHgyAHXRuS4PIjY9K2BGM5vI\n" +"seA2GEdAJNmZPAQJE5rxkrsAH9n8QtmHucEqzCZVFcLuCwIDAQABo3AwbjAJBgNV\n" +"HRMEAjAAMB0GA1UdDgQWBBSMgUaKY3L65wH5M4il/gbHCeVm4TAfBgNVHSMEGDAW\n" +"gBTl/kZGRoa0cm82zW7CPn3yqk4MeTAOBgNVHQ8BAQEEBAMCAYAwEQYJYIZIAYb4\n" +"QgEBBAQDAgAQMA0GCSqGSIb3DQEBBQUAA4ICAQAdmpf8k+ZKuhDvNwMCrf1JIZh3\n" +"uJxlCHFke/ypsMT2E6p/GZpD/lLyRHbk7V5aEYdmBaK6Dem0KYhRuDclWscpQdXl\n" +"96wx1IDNueMkj5ZDmpBLFl/nqxlM9HfHo8YTE9dRgzJAR8+dFR8HyRSayKo+pz4L\n" +"FkNFT5Jtm9kKLIN+mSGKMBmpY4owfpeh7K6YyASoOHL9Zk8A0I7iZX8FB5KujrlG\n" +"WJahjSAyvLvy98XDCf9/SyX73F1ol5ycAb/du+G5VZFDEI8sv/7fIdTx/AUR30Ac\n" +"f3tqXZ4HwxWc0gofT0J2z/I4FZ/sT/1SNHReGNrG9GNn5bxjwpSXfc5A1bjhRfxd\n" +"x73xKEInjpgo6AXY7wfNk1V+2z7keVOpaDEZUOsd/x/C+L8FsUh2JJHZp/hKX6Co\n" +"AD///pxqNfvH5pPLUINC7VRUOTynUas7p9UvkPeJjqnWY6pmjeb4Fs6Z6vn0+Opy\n" +"HP1MjLL41a+U9VxuNb6SfRDoeT19pqK6ovT2gbc61OvTI0lE97ChC622rjnV0c/N\n" +"QYqkeTQG/IjPk0QFrYQxMqq6QKgds2nheYd4LyLGhk72pKWr28Hfj1ElcoTFFbWP\n" +"ndI+uZePkkCsVYNMXbIAIpqLb++1ftl+L+itqxTyq+0tPObIL3WG9rzBGz8X6WT0\n" +"KIzi4KAn66e5/iWZng==\n" +"-----END CERTIFICATE-----\n"; + +static const size_t public_key_codesign_pem_size = 2025; + #endif