@@ -690,7 +690,7 @@ static EFI_STATUS check_whitelist (WIN_CERTIFICATE_EFI_PKCS *cert,
690690 }
691691
692692 update_verification_method (VERIFIED_BY_NOTHING );
693- return EFI_SECURITY_VIOLATION ;
693+ return EFI_NOT_FOUND ;
694694}
695695
696696/*
@@ -1004,129 +1004,238 @@ static EFI_STATUS generate_hash (char *data, unsigned int datasize_in,
10041004 return efi_status ;
10051005}
10061006
1007+ static EFI_STATUS
1008+ verify_one_signature (WIN_CERTIFICATE_EFI_PKCS * sig ,
1009+ UINT8 * sha256hash , UINT8 * sha1hash )
1010+ {
1011+ EFI_STATUS efi_status ;
1012+
1013+ /*
1014+ * Ensure that the binary isn't blacklisted
1015+ */
1016+ drain_openssl_errors ();
1017+ efi_status = check_blacklist (sig , sha256hash , sha1hash );
1018+ if (EFI_ERROR (efi_status )) {
1019+ perror (L"Binary is blacklisted: %r\n" , efi_status );
1020+ PrintErrors ();
1021+ ClearErrors ();
1022+ crypterr (efi_status );
1023+ return efi_status ;
1024+ }
1025+
1026+ /*
1027+ * Check whether the binary is whitelisted in any of the firmware
1028+ * databases
1029+ */
1030+ drain_openssl_errors ();
1031+ efi_status = check_whitelist (sig , sha256hash , sha1hash );
1032+ if (EFI_ERROR (efi_status )) {
1033+ if (efi_status != EFI_NOT_FOUND ) {
1034+ dprint (L"check_whitelist(): %r\n" , efi_status );
1035+ PrintErrors ();
1036+ ClearErrors ();
1037+ crypterr (efi_status );
1038+ }
1039+ } else {
1040+ drain_openssl_errors ();
1041+ return efi_status ;
1042+ }
1043+
1044+ efi_status = EFI_NOT_FOUND ;
1045+ #if defined(ENABLE_SHIM_CERT )
1046+ /*
1047+ * Check against the shim build key
1048+ */
1049+ drain_openssl_errors ();
1050+ if (build_cert && build_cert_size ) {
1051+ dprint ("verifying against shim cert\n" );
1052+ }
1053+ if (build_cert && build_cert_size &&
1054+ AuthenticodeVerify (sig -> CertData ,
1055+ sig -> Hdr .dwLength - sizeof (sig -> Hdr ),
1056+ build_cert , build_cert_size , sha256hash ,
1057+ SHA256_DIGEST_SIZE )) {
1058+ dprint (L"AuthenticodeVerify(shim_cert) succeeded\n" );
1059+ update_verification_method (VERIFIED_BY_CERT );
1060+ tpm_measure_variable (L"Shim" , SHIM_LOCK_GUID ,
1061+ build_cert_size , build_cert );
1062+ efi_status = EFI_SUCCESS ;
1063+ drain_openssl_errors ();
1064+ return efi_status ;
1065+ } else {
1066+ dprint (L"AuthenticodeVerify(shim_cert) failed\n" );
1067+ PrintErrors ();
1068+ ClearErrors ();
1069+ crypterr (EFI_NOT_FOUND );
1070+ }
1071+ #endif /* defined(ENABLE_SHIM_CERT) */
1072+
1073+ #if defined(VENDOR_CERT_FILE )
1074+ /*
1075+ * And finally, check against shim's built-in key
1076+ */
1077+ drain_openssl_errors ();
1078+ if (vendor_cert_size ) {
1079+ dprint ("verifying against vendor_cert\n" );
1080+ }
1081+ if (vendor_cert_size &&
1082+ AuthenticodeVerify (sig -> CertData ,
1083+ sig -> Hdr .dwLength - sizeof (sig -> Hdr ),
1084+ vendor_cert , vendor_cert_size ,
1085+ sha256hash , SHA256_DIGEST_SIZE )) {
1086+ dprint (L"AuthenticodeVerify(vendor_cert) succeeded\n" );
1087+ update_verification_method (VERIFIED_BY_CERT );
1088+ tpm_measure_variable (L"Shim" , SHIM_LOCK_GUID ,
1089+ vendor_cert_size , vendor_cert );
1090+ efi_status = EFI_SUCCESS ;
1091+ drain_openssl_errors ();
1092+ return efi_status ;
1093+ } else {
1094+ dprint (L"AuthenticodeVerify(vendor_cert) failed\n" );
1095+ PrintErrors ();
1096+ ClearErrors ();
1097+ crypterr (EFI_NOT_FOUND );
1098+ }
1099+ #endif /* defined(VENDOR_CERT_FILE) */
1100+
1101+ return efi_status ;
1102+ }
1103+
10071104/*
10081105 * Check that the signature is valid and matches the binary
10091106 */
10101107static EFI_STATUS verify_buffer (char * data , int datasize ,
10111108 PE_COFF_LOADER_IMAGE_CONTEXT * context ,
10121109 UINT8 * sha256hash , UINT8 * sha1hash )
10131110{
1014- EFI_STATUS efi_status = EFI_SECURITY_VIOLATION ;
1015- WIN_CERTIFICATE_EFI_PKCS * cert = NULL ;
1016- unsigned int size = datasize ;
1111+ EFI_STATUS ret_efi_status ;
1112+ size_t size = datasize ;
1113+ size_t offset = 0 ;
1114+ unsigned int i = 0 ;
10171115
10181116 if (datasize < 0 )
10191117 return EFI_INVALID_PARAMETER ;
10201118
1021- if (context -> SecDir -> Size != 0 ) {
1022- if (context -> SecDir -> Size >= size ) {
1023- perror (L"Certificate Database size is too large\n" );
1024- return EFI_INVALID_PARAMETER ;
1025- }
1026-
1027- cert = ImageAddress (data , size ,
1028- context -> SecDir -> VirtualAddress );
1029-
1030- if (!cert ) {
1031- perror (L"Certificate located outside the image\n" );
1032- return EFI_INVALID_PARAMETER ;
1033- }
1034-
1035- if (cert -> Hdr .dwLength > context -> SecDir -> Size ) {
1036- perror (L"Certificate list size is inconsistent with PE headers" );
1037- return EFI_INVALID_PARAMETER ;
1038- }
1039-
1040- if (cert -> Hdr .wCertificateType !=
1041- WIN_CERT_TYPE_PKCS_SIGNED_DATA ) {
1042- perror (L"Unsupported certificate type %x\n" ,
1043- cert -> Hdr .wCertificateType );
1044- return EFI_UNSUPPORTED ;
1045- }
1046- }
1047-
10481119 /*
10491120 * Clear OpenSSL's error log, because we get some DSO unimplemented
10501121 * errors during its intialization, and we don't want those to look
10511122 * like they're the reason for validation failures.
10521123 */
10531124 drain_openssl_errors ();
10541125
1055- efi_status = generate_hash (data , datasize , context , sha256hash , sha1hash );
1056- if (EFI_ERROR (efi_status )) {
1057- LogError (L"generate_hash: %r\n" , efi_status );
1058- return efi_status ;
1126+ ret_efi_status = generate_hash (data , datasize , context , sha256hash , sha1hash );
1127+ if (EFI_ERROR (ret_efi_status )) {
1128+ dprint (L"generate_hash: %r\n" , ret_efi_status );
1129+ PrintErrors ();
1130+ ClearErrors ();
1131+ crypterr (ret_efi_status );
1132+ return ret_efi_status ;
10591133 }
10601134
10611135 /*
1062- * Ensure that the binary isn't blacklisted
1136+ * Ensure that the binary isn't blacklisted by hash
10631137 */
1064- efi_status = check_blacklist (cert , sha256hash , sha1hash );
1065- if (EFI_ERROR (efi_status )) {
1138+ drain_openssl_errors ();
1139+ ret_efi_status = check_blacklist (NULL , sha256hash , sha1hash );
1140+ if (EFI_ERROR (ret_efi_status )) {
10661141 perror (L"Binary is blacklisted\n" );
1067- LogError (L"Binary is blacklisted: %r\n" , efi_status );
1068- return efi_status ;
1142+ dprint (L"Binary is blacklisted: %r\n" , ret_efi_status );
1143+ PrintErrors ();
1144+ ClearErrors ();
1145+ crypterr (ret_efi_status );
1146+ return ret_efi_status ;
10691147 }
10701148
10711149 /*
1072- * Check whether the binary is whitelisted in any of the firmware
1073- * databases
1150+ * Check whether the binary is whitelisted by hash in any of the
1151+ * firmware databases
10741152 */
1075- efi_status = check_whitelist (cert , sha256hash , sha1hash );
1076- if (EFI_ERROR (efi_status )) {
1077- LogError (L"check_whitelist(): %r\n" , efi_status );
1153+ drain_openssl_errors ();
1154+ ret_efi_status = check_whitelist (NULL , sha256hash , sha1hash );
1155+ if (EFI_ERROR (ret_efi_status )) {
1156+ dprint (L"check_whitelist: %r\n" , ret_efi_status );
1157+ if (ret_efi_status != EFI_NOT_FOUND ) {
1158+ PrintErrors ();
1159+ ClearErrors ();
1160+ crypterr (ret_efi_status );
1161+ return ret_efi_status ;
1162+ }
10781163 } else {
10791164 drain_openssl_errors ();
1080- return efi_status ;
1165+ return ret_efi_status ;
10811166 }
10821167
1083- if (cert ) {
1084- #if defined(ENABLE_SHIM_CERT )
1085- /*
1086- * Check against the shim build key
1087- */
1088- if (sizeof (shim_cert ) &&
1089- AuthenticodeVerify (cert -> CertData ,
1090- cert -> Hdr .dwLength - sizeof (cert -> Hdr ),
1091- shim_cert , sizeof (shim_cert ), sha256hash ,
1092- SHA256_DIGEST_SIZE )) {
1093- update_verification_method (VERIFIED_BY_CERT );
1094- tpm_measure_variable (L"Shim" , SHIM_LOCK_GUID ,
1095- sizeof (shim_cert ), shim_cert );
1096- efi_status = EFI_SUCCESS ;
1097- drain_openssl_errors ();
1098- return efi_status ;
1099- } else {
1100- LogError (L"AuthenticodeVerify(shim_cert) failed\n" );
1168+ if (context -> SecDir -> Size == 0 ) {
1169+ dprint (L"No signatures found\n" );
1170+ return EFI_SECURITY_VIOLATION ;
1171+ }
1172+
1173+ if (context -> SecDir -> Size >= size ) {
1174+ perror (L"Certificate Database size is too large\n" );
1175+ return EFI_INVALID_PARAMETER ;
1176+ }
1177+
1178+ ret_efi_status = EFI_NOT_FOUND ;
1179+ do {
1180+ WIN_CERTIFICATE_EFI_PKCS * sig = NULL ;
1181+ size_t sz ;
1182+
1183+ sig = ImageAddress (data , size ,
1184+ context -> SecDir -> VirtualAddress + offset );
1185+ if (!sig )
1186+ break ;
1187+
1188+ sz = offset + offsetof(WIN_CERTIFICATE_EFI_PKCS , Hdr .dwLength )
1189+ + sizeof (sig -> Hdr .dwLength );
1190+ if (sz > context -> SecDir -> Size ) {
1191+ perror (L"Certificate size is too large for secruity database" );
1192+ return EFI_INVALID_PARAMETER ;
11011193 }
1102- #endif /* defined(ENABLE_SHIM_CERT) */
11031194
1104- #if defined(VENDOR_CERT_FILE )
1105- /*
1106- * And finally, check against shim's built-in key
1107- */
1108- if (vendor_authorized_size &&
1109- AuthenticodeVerify (cert -> CertData ,
1110- cert -> Hdr .dwLength - sizeof (cert -> Hdr ),
1111- vendor_authorized , vendor_authorized_size ,
1112- sha256hash , SHA256_DIGEST_SIZE )) {
1113- update_verification_method (VERIFIED_BY_CERT );
1114- tpm_measure_variable (L"Shim" , SHIM_LOCK_GUID ,
1115- vendor_authorized_size , vendor_authorized );
1116- efi_status = EFI_SUCCESS ;
1117- drain_openssl_errors ();
1118- return efi_status ;
1195+ sz = sig -> Hdr .dwLength ;
1196+ if (sz > context -> SecDir -> Size - offset ) {
1197+ perror (L"Certificate size is too large for secruity database" );
1198+ return EFI_INVALID_PARAMETER ;
1199+ }
1200+
1201+ if (sz < sizeof (sig -> Hdr )) {
1202+ perror (L"Certificate size is too small for certificate data" );
1203+ return EFI_INVALID_PARAMETER ;
1204+ }
1205+
1206+ if (sig -> Hdr .wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA ) {
1207+ EFI_STATUS efi_status ;
1208+
1209+ dprint (L"Attempting to verify signature %d:\n" , i ++ );
1210+
1211+ efi_status = verify_one_signature (sig , sha256hash , sha1hash );
1212+
1213+ /*
1214+ * If we didn't get EFI_SECURITY_VIOLATION from
1215+ * checking the hashes above, then any dbx entries are
1216+ * for a certificate, not this individual binary.
1217+ *
1218+ * So don't clobber successes with security violation
1219+ * here; that just means it isn't a success.
1220+ */
1221+ if (ret_efi_status != EFI_SUCCESS )
1222+ ret_efi_status = efi_status ;
11191223 } else {
1120- LogError (L"AuthenticodeVerify(vendor_authorized) failed\n" );
1224+ perror (L"Unsupported certificate type %x\n" ,
1225+ sig -> Hdr .wCertificateType );
11211226 }
1122- #endif /* defined(VENDOR_CERT_FILE) */
1123- }
1227+ offset = ALIGN_VALUE ( offset + sz , 8 );
1228+ } while ( offset < context -> SecDir -> Size );
11241229
1125- LogError (L"Binary is not whitelisted\n" );
1126- crypterr (EFI_SECURITY_VIOLATION );
1127- PrintErrors ();
1128- efi_status = EFI_SECURITY_VIOLATION ;
1129- return efi_status ;
1230+ if (ret_efi_status != EFI_SUCCESS ) {
1231+ dprint (L"Binary is not whitelisted\n" );
1232+ PrintErrors ();
1233+ ClearErrors ();
1234+ crypterr (EFI_SECURITY_VIOLATION );
1235+ ret_efi_status = EFI_SECURITY_VIOLATION ;
1236+ }
1237+ drain_openssl_errors ();
1238+ return ret_efi_status ;
11301239}
11311240
11321241/*
0 commit comments