From f110c89b169505156741ee4ce4b0952e899ed0d8 Mon Sep 17 00:00:00 2001 From: Gary Ching-Pang Lin Date: Thu, 3 Apr 2014 18:26:37 +0800 Subject: [PATCH 1/5] MokManager: Support SHA1 hash in MOK Add SHA1 hash support and amend the code to make it easier to support other SHA digests. --- MokManager.c | 121 ++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 75 insertions(+), 46 deletions(-) Index: shim-0.7/MokManager.c =================================================================== --- shim-0.7.orig/MokManager.c +++ shim-0.7/MokManager.c @@ -25,6 +25,9 @@ #define EFI_VARIABLE_APPEND_WRITE 0x00000040 EFI_GUID SHIM_LOCK_GUID = { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} }; +EFI_GUID EFI_CERT_SHA224_GUID = { 0xb6e5233, 0xa65c, 0x44c9, {0x94, 0x7, 0xd9, 0xab, 0x83, 0xbf, 0xc8, 0xbd} }; +EFI_GUID EFI_CERT_SHA384_GUID = { 0xff3e5307, 0x9fd0, 0x48c9, {0x85, 0xf1, 0x8a, 0xd5, 0x6c, 0x70, 0x1e, 0x1} }; +EFI_GUID EFI_CERT_SHA512_GUID = { 0x93e0fae, 0xa6c4, 0x4f50, {0x9f, 0x1b, 0xd4, 0x1e, 0x2b, 0x89, 0xc1, 0x9a} }; #define CERT_STRING L"Select an X509 certificate to enroll:\n\n" #define HASH_STRING L"Select a file to trust:\n\n" @@ -93,31 +96,84 @@ done: return status; } +static BOOLEAN is_sha_hash (EFI_GUID Type) +{ + EFI_GUID Sha1 = EFI_CERT_SHA1_GUID; + EFI_GUID Sha224 = EFI_CERT_SHA224_GUID; + EFI_GUID Sha256 = EFI_CERT_SHA256_GUID; + EFI_GUID Sha384 = EFI_CERT_SHA384_GUID; + EFI_GUID Sha512 = EFI_CERT_SHA512_GUID; + + if (CompareGuid(&Type, &Sha1) == 0) + return TRUE; + else if (CompareGuid(&Type, &Sha224) == 0) + return TRUE; + else if (CompareGuid(&Type, &Sha256) == 0) + return TRUE; + else if (CompareGuid(&Type, &Sha384) == 0) + return TRUE; + else if (CompareGuid(&Type, &Sha512) == 0) + return TRUE; + + return FALSE; +} + +static UINT32 sha_size (EFI_GUID Type) +{ + EFI_GUID Sha1 = EFI_CERT_SHA1_GUID; + EFI_GUID Sha224 = EFI_CERT_SHA224_GUID; + EFI_GUID Sha256 = EFI_CERT_SHA256_GUID; + EFI_GUID Sha384 = EFI_CERT_SHA384_GUID; + EFI_GUID Sha512 = EFI_CERT_SHA512_GUID; + + if (CompareGuid(&Type, &Sha1) == 0) + return SHA1_DIGEST_SIZE; + else if (CompareGuid(&Type, &Sha224) == 0) + return SHA224_DIGEST_LENGTH; + else if (CompareGuid(&Type, &Sha256) == 0) + return SHA256_DIGEST_SIZE; + else if (CompareGuid(&Type, &Sha384) == 0) + return SHA384_DIGEST_LENGTH; + else if (CompareGuid(&Type, &Sha512) == 0) + return SHA512_DIGEST_LENGTH; + + return 0; +} + +static BOOLEAN is_valid_siglist (EFI_GUID Type, UINT32 SigSize) +{ + EFI_GUID CertType = X509_GUID; + UINT32 hash_sig_size; + + if (CompareGuid (&Type, &CertType) == 0 && SigSize != 0) + return TRUE; + + if (!is_sha_hash (Type)) + return FALSE; + + hash_sig_size = sha_size (Type) + sizeof(EFI_GUID); + if (SigSize != hash_sig_size) + return FALSE; + + return TRUE; +} + static UINT32 count_keys(void *Data, UINTN DataSize) { EFI_SIGNATURE_LIST *CertList = Data; - EFI_GUID CertType = X509_GUID; - EFI_GUID HashType = EFI_CERT_SHA256_GUID; UINTN dbsize = DataSize; UINT32 MokNum = 0; while ((dbsize > 0) && (dbsize >= CertList->SignatureListSize)) { - if ((CompareGuid (&CertList->SignatureType, &CertType) != 0) && - (CompareGuid (&CertList->SignatureType, &HashType) != 0)) { - console_notify(L"Doesn't look like a key or hash"); - dbsize -= CertList->SignatureListSize; - CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + - CertList->SignatureListSize); - continue; + if (CertList->SignatureListSize == 0 || + CertList->SignatureListSize <= CertList->SignatureSize) { + console_errorbox(L"Corrupted signature list"); + return 0; } - if ((CompareGuid (&CertList->SignatureType, &CertType) != 0) && - (CertList->SignatureSize != 48)) { - console_notify(L"Doesn't look like a valid hash"); - dbsize -= CertList->SignatureListSize; - CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + - CertList->SignatureListSize); - continue; + if (!is_valid_siglist(CertList->SignatureType, CertList->SignatureSize)) { + console_errorbox(L"Invalid signature list found"); + return 0; } MokNum++; @@ -134,7 +190,6 @@ static MokListNode *build_mok_list(UINT3 EFI_SIGNATURE_LIST *CertList = Data; EFI_SIGNATURE_DATA *Cert; EFI_GUID CertType = X509_GUID; - EFI_GUID HashType = EFI_CERT_SHA256_GUID; UINTN dbsize = DataSize; UINTN count = 0; @@ -146,21 +201,8 @@ static MokListNode *build_mok_list(UINT3 } while ((dbsize > 0) && (dbsize >= CertList->SignatureListSize)) { - if ((CompareGuid (&CertList->SignatureType, &CertType) != 0) && - (CompareGuid (&CertList->SignatureType, &HashType) != 0)) { - dbsize -= CertList->SignatureListSize; - CertList = (EFI_SIGNATURE_LIST *)((UINT8 *) CertList + - CertList->SignatureListSize); - continue; - } - - if ((CompareGuid (&CertList->SignatureType, &HashType) == 0) && - (CertList->SignatureSize != 48)) { - dbsize -= CertList->SignatureListSize; - CertList = (EFI_SIGNATURE_LIST *)((UINT8 *) CertList + - CertList->SignatureListSize); - continue; - } + /* Omit the signature check here since we already did it + in count_keys() */ Cert = (EFI_SIGNATURE_DATA *) (((UINT8 *) CertList) + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize); @@ -380,22 +422,46 @@ static void show_x509_info (X509 *X509Ce FreePool(text); } -static void show_sha256_digest (UINT8 *hash) +static void show_sha_digest (EFI_GUID Type, UINT8 *hash) { + EFI_GUID Sha1 = EFI_CERT_SHA1_GUID; + EFI_GUID Sha224 = EFI_CERT_SHA224_GUID; + EFI_GUID Sha256 = EFI_CERT_SHA256_GUID; + EFI_GUID Sha384 = EFI_CERT_SHA384_GUID; + EFI_GUID Sha512 = EFI_CERT_SHA512_GUID; CHAR16 *text[5]; POOL_PRINT hash_string1; POOL_PRINT hash_string2; int i; + int length; + + if (CompareGuid(&Type, &Sha1) == 0) { + length = SHA1_DIGEST_SIZE; + text[0] = L"SHA1 hash"; + } else if (CompareGuid(&Type, &Sha224) == 0) { + length = SHA224_DIGEST_LENGTH; + text[0] = L"SHA224 hash"; + } else if (CompareGuid(&Type, &Sha256) == 0) { + length = SHA256_DIGEST_SIZE; + text[0] = L"SHA256 hash"; + } else if (CompareGuid(&Type, &Sha384) == 0) { + length = SHA384_DIGEST_LENGTH; + text[0] = L"SHA384 hash"; + } else if (CompareGuid(&Type, &Sha512) == 0) { + length = SHA512_DIGEST_LENGTH; + text[0] = L"SHA512 hash"; + } else { + return; + } ZeroMem(&hash_string1, sizeof(hash_string1)); ZeroMem(&hash_string2, sizeof(hash_string2)); - text[0] = L"SHA256 hash"; text[1] = L""; - for (i=0; i<16; i++) + for (i=0; iSignatureListSize = list[i].MokSize + sizeof(EFI_SIGNATURE_LIST); - CertList->SignatureSize = SHA256_DIGEST_SIZE + sizeof(EFI_GUID); + CertList->SignatureSize = sha_size(list[i].Type) + sizeof(EFI_GUID); CopyMem(CertData, list[i].Mok, list[i].MokSize); } @@ -1043,10 +1111,9 @@ static void mem_move (void *dest, void * d[i] = s[i]; } -static void delete_hash_in_list (UINT8 *hash, UINT32 hash_size, +static void delete_hash_in_list (EFI_GUID Type, UINT8 *hash, UINT32 hash_size, MokListNode *mok, INTN mok_num) { - EFI_GUID HashType = EFI_CERT_SHA256_GUID; UINT32 sig_size; UINT32 list_num; int i, del_ind; @@ -1056,7 +1123,7 @@ static void delete_hash_in_list (UINT8 * sig_size = hash_size + sizeof(EFI_GUID); for (i = 0; i < mok_num; i++) { - if ((CompareGuid(&(mok[i].Type), &HashType) != 0) || + if ((CompareGuid(&(mok[i].Type), &Type) != 0) || (mok[i].MokSize < sig_size)) continue; @@ -1086,7 +1153,7 @@ static void delete_hash_in_list (UINT8 * } } -static void delete_hash_list (void *hash_list, UINT32 list_size, +static void delete_hash_list (EFI_GUID Type, void *hash_list, UINT32 list_size, MokListNode *mok, INTN mok_num) { UINT32 hash_size; @@ -1095,7 +1162,7 @@ static void delete_hash_list (void *hash UINT8 *hash; int i; - hash_size = SHA256_DIGEST_SIZE; + hash_size = sha_size (Type); sig_size = hash_size + sizeof(EFI_GUID); if (list_size < sig_size) return; @@ -1105,7 +1172,7 @@ static void delete_hash_list (void *hash hash = hash_list + sizeof(EFI_GUID); for (i = 0; i < hash_num; i++) { - delete_hash_in_list (hash, hash_size, mok, mok_num); + delete_hash_in_list (Type, hash, hash_size, mok, mok_num); hash += sig_size; } } @@ -1114,7 +1181,6 @@ static EFI_STATUS delete_keys (void *Mok { EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; EFI_GUID CertType = X509_GUID; - EFI_GUID HashType = EFI_CERT_SHA256_GUID; EFI_STATUS efi_status; CHAR16 *db_name; CHAR16 *auth_name; @@ -1161,7 +1227,13 @@ static EFI_STATUS delete_keys (void *Mok efi_status = get_variable_attr (db_name, &MokListData, &MokListDataSize, shim_lock_guid, &attributes); - if (attributes & EFI_VARIABLE_RUNTIME_ACCESS) { + if (efi_status != EFI_SUCCESS) { + if (MokX) + console_errorbox(L"Failed to retrieve MokListX"); + else + console_errorbox(L"Failed to retrieve MokList"); + return EFI_ABORTED; + } else if (attributes & EFI_VARIABLE_RUNTIME_ACCESS) { if (MokX) { err_str1 = L"MokListX is compromised!"; err_str2 = L"Erase all keys in MokListX!"; @@ -1170,7 +1242,11 @@ static EFI_STATUS delete_keys (void *Mok err_str2 = L"Erase all keys in MokList!"; } console_alertbox((CHAR16 *[]){err_str1, err_str2, NULL}); - LibDeleteVariable(db_name, &shim_lock_guid); + uefi_call_wrapper(RT->SetVariable, 5, db_name, + &shim_lock_guid, + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS, + 0, NULL); return EFI_ACCESS_DENIED; } @@ -1180,23 +1256,56 @@ static EFI_STATUS delete_keys (void *Mok /* Construct lists */ mok_num = count_keys(MokListData, MokListDataSize); + if (mok_num == 0) { + if (MokX) { + err_str1 = L"Failed to construct the key list of MokListX"; + err_str2 = L"Reset MokListX!"; + } else { + err_str1 = L"Failed to construct the key list of MokList"; + err_str2 = L"Reset MokList!"; + } + console_alertbox((CHAR16 *[]){err_str1, err_str2, NULL}); + uefi_call_wrapper(RT->SetVariable, 5, db_name, + &shim_lock_guid, + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS, + 0, NULL); + efi_status = EFI_ABORTED; + goto error; + } mok = build_mok_list(mok_num, MokListData, MokListDataSize); + if (!mok) { + console_errorbox(L"Failed to construct key list"); + efi_status = EFI_ABORTED; + goto error; + } del_num = count_keys(MokDel, MokDelSize); + if (del_num == 0) { + console_errorbox(L"Invalid key delete list"); + efi_status = EFI_ABORTED; + goto error; + } del_key = build_mok_list(del_num, MokDel, MokDelSize); + if (!del_key) { + console_errorbox(L"Failed to construct key list"); + efi_status = EFI_ABORTED; + goto error; + } /* Search and destroy */ for (i = 0; i < del_num; i++) { if (CompareGuid(&(del_key[i].Type), &CertType) == 0) { delete_cert(del_key[i].Mok, del_key[i].MokSize, mok, mok_num); - } else if (CompareGuid(&(del_key[i].Type), &HashType) == 0) { - delete_hash_list(del_key[i].Mok, del_key[i].MokSize, - mok, mok_num); + } else if (is_sha_hash(del_key[i].Type)) { + delete_hash_list(del_key[i].Type, del_key[i].Mok, + del_key[i].MokSize, mok, mok_num); } } efi_status = write_back_mok_list(mok, mok_num, MokX); +error: if (MokListData) FreePool(MokListData); if (mok)