From ae604d43bdb9b4fa8d3d126f53c1be2c97e4a960 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Fri, 1 Dec 2023 17:11:47 -0800 Subject: [PATCH 01/10] Clean up Strong Name code --- src/coreclr/ilasm/asmman.cpp | 22 ---- src/coreclr/ilasm/asmman.hpp | 1 - src/coreclr/ilasm/writer.cpp | 2 +- src/coreclr/inc/strongnameinternal.h | 18 --- src/coreclr/md/runtime/strongnameinternal.cpp | 115 ++++++++---------- src/coreclr/vm/methodtablebuilder.cpp | 1 - 6 files changed, 51 insertions(+), 108 deletions(-) diff --git a/src/coreclr/ilasm/asmman.cpp b/src/coreclr/ilasm/asmman.cpp index 4234786baafd9..01bbf4edc994b 100644 --- a/src/coreclr/ilasm/asmman.cpp +++ b/src/coreclr/ilasm/asmman.cpp @@ -448,27 +448,6 @@ void AsmMan::EndAssembly() } CloseHandle(hFile); - - // Guess whether we're full or delay signing based on - // whether the blob passed to us looks like a public - // key. (I.e. we may just have copied a full key pair - // into the public key buffer). - if (m_sStrongName.m_cbPublicKey >= sizeof(PublicKeyBlob) && - (offsetof(PublicKeyBlob, PublicKey) + - VAL32(((PublicKeyBlob*)m_sStrongName.m_pbPublicKey)->cbPublicKey)) == m_sStrongName.m_cbPublicKey) - m_sStrongName.m_fFullSign = FALSE; - else - m_sStrongName.m_fFullSign = TRUE; - - // If we really have a key pair, we'll move it into a - // key container so the signing code gets the key pair - // from a consistent place. - if (m_sStrongName.m_fFullSign) - { - report->error("Error: ilasm on CoreCLR does not support full sign.\n"); - m_pCurAsmRef = NULL; - return; - } } } else @@ -485,7 +464,6 @@ void AsmMan::EndAssembly() } m_sStrongName.m_wzKeyContainer = NULL; - m_sStrongName.m_fFullSign = FALSE; m_sStrongName.m_dwPublicKeyAllocated = AsmManStrongName::NotAllocated; } } diff --git a/src/coreclr/ilasm/asmman.hpp b/src/coreclr/ilasm/asmman.hpp index db4765e069418..a8dd0516bc3a9 100644 --- a/src/coreclr/ilasm/asmman.hpp +++ b/src/coreclr/ilasm/asmman.hpp @@ -138,7 +138,6 @@ struct AsmManStrongName BYTE *m_pbPrivateKey; DWORD m_cbPrivateKey; WCHAR *m_wzKeyContainer; - BOOL m_fFullSign; // Where has the memory pointed to by m_pbPublicKey been taken from: AllocationState m_dwPublicKeyAllocated; diff --git a/src/coreclr/ilasm/writer.cpp b/src/coreclr/ilasm/writer.cpp index 6f96b0bd632f1..d971c7f190d9e 100644 --- a/src/coreclr/ilasm/writer.cpp +++ b/src/coreclr/ilasm/writer.cpp @@ -1034,7 +1034,7 @@ HRESULT Assembler::CreatePEFile(_In_ __nullterminated WCHAR *pwzOutputFilename) goto exit; } - // Public-sign by default + // CoreCLR ILAsm only supports public signing m_dwComImageFlags |= COMIMAGE_FLAGS_STRONGNAMESIGNED; } diff --git a/src/coreclr/inc/strongnameinternal.h b/src/coreclr/inc/strongnameinternal.h index 7924400ec5063..f0337cc988fd2 100644 --- a/src/coreclr/inc/strongnameinternal.h +++ b/src/coreclr/inc/strongnameinternal.h @@ -7,24 +7,6 @@ #ifndef _STRONGNAME_INTERNAL_H #define _STRONGNAME_INTERNAL_H -// Public key blob binary format. -typedef struct { - unsigned int SigAlgID; // (ALG_ID) signature algorithm used to create the signature - unsigned int HashAlgID; // (ALG_ID) hash algorithm used to create the signature - ULONG cbPublicKey; // length of the key in bytes - BYTE PublicKey[1]; // variable length byte array containing the key value in format output by CryptoAPI -} PublicKeyBlob; - -// Determine the number of bytes in a public key -DWORD StrongNameSizeOfPublicKey(const PublicKeyBlob &keyPublicKey); - -bool StrongNameIsValidPublicKey(_In_reads_(cbPublicKeyBlob) const BYTE *pbPublicKeyBlob, DWORD cbPublicKeyBlob); -bool StrongNameIsValidPublicKey(const PublicKeyBlob &keyPublicKey); - -// Determine if a public key is the ECMA key -bool StrongNameIsEcmaKey(_In_reads_(cbKey) const BYTE *pbKey, DWORD cbKey); -bool StrongNameIsEcmaKey(const PublicKeyBlob &keyPublicKey); - HRESULT StrongNameTokenFromPublicKey(BYTE* pbPublicKeyBlob, // [in] public key blob ULONG cbPublicKeyBlob, BYTE** ppbStrongNameToken, // [out] strong name token diff --git a/src/coreclr/md/runtime/strongnameinternal.cpp b/src/coreclr/md/runtime/strongnameinternal.cpp index f7e43a79bb27a..f3b9683ac5bf3 100644 --- a/src/coreclr/md/runtime/strongnameinternal.cpp +++ b/src/coreclr/md/runtime/strongnameinternal.cpp @@ -6,20 +6,36 @@ #include "stdafx.h" #include "strongnameinternal.h" +#include "sha1.h" + +// We allow a special abbreviated form of the Microsoft public key (16 bytes +// long: 0 for both alg ids, 4 for key length and 4 bytes of 0 for the key +// itself). This allows us to build references to system libraries that are +// platform neutral (so a 3rd party can build SPCL replacements). The +// special zero PK is just shorthand for the local runtime's real system PK, +// which is always used to perform the signature verification, so no security +// hole is opened by this. Therefore we need to store a copy of the real PK (for +// this platform) here. #include "thekey.h" #include "ecmakey.h" -#include "sha1.h" + +// Public key blob binary format. +typedef struct { + unsigned int SigAlgID; // (ALG_ID) signature algorithm used to create the signature + unsigned int HashAlgID; // (ALG_ID) hash algorithm used to create the signature + ULONG cbPublicKey; // length of the key in bytes + BYTE PublicKey[1]; // variable length byte array containing the key value in format output by CryptoAPI +} PublicKeyBlob; //--------------------------------------------------------------------------------------- // -// Check to see if a public key blob is the ECMA public key blob +// Determine the number of bytes that a public key blob occupies, including the key portion // // Arguments: -// pbKey - public key blob to check -// cbKey - size in bytes of pbKey +// keyPublicKey - key blob to calculate the size of // -bool StrongNameIsEcmaKey(_In_reads_(cbKey) const BYTE *pbKey, DWORD cbKey) +DWORD StrongNameSizeOfPublicKey(const PublicKeyBlob &keyPublicKey) { CONTRACTL { @@ -28,14 +44,8 @@ bool StrongNameIsEcmaKey(_In_reads_(cbKey) const BYTE *pbKey, DWORD cbKey) } CONTRACTL_END; - // The key should be the same size as the ECMA key - if (cbKey != sizeof(g_rbNeutralPublicKey)) - { - return false; - } - - const PublicKeyBlob *pKeyBlob = reinterpret_cast(pbKey); - return StrongNameIsEcmaKey(*pKeyBlob); + return offsetof(PublicKeyBlob, PublicKey) + // Size of the blob header plus + GET_UNALIGNED_VAL32(&keyPublicKey.cbPublicKey); // the number of bytes in the key } //--------------------------------------------------------------------------------------- @@ -61,38 +71,30 @@ bool StrongNameIsEcmaKey(const PublicKeyBlob &keyPublicKey) //--------------------------------------------------------------------------------------- // -// Verify that a public key blob looks like a reasonable public key +// Check to see if a public key blob is the ECMA public key blob // // Arguments: -// pbBuffer - buffer to verify the format of -// cbBuffer - size of pbBuffer +// pbKey - public key blob to check +// cbKey - size in bytes of pbKey // -bool StrongNameIsValidPublicKey(_In_reads_(cbBuffer) const BYTE *pbBuffer, DWORD cbBuffer) +bool StrongNameIsEcmaKey(_In_reads_(cbKey) const BYTE *pbKey, DWORD cbKey) { CONTRACTL { - PRECONDITION(CheckPointer(pbBuffer)); NOTHROW; GC_NOTRIGGER; } CONTRACTL_END; - // The buffer must be at least as large as the public key structure - if (cbBuffer < sizeof(PublicKeyBlob)) - { - return false; - } - - // The buffer must be the same size as the structure header plus the trailing key data - const PublicKeyBlob *pkeyPublicKey = reinterpret_cast(pbBuffer); - if (GET_UNALIGNED_VAL32(&pkeyPublicKey->cbPublicKey) != cbBuffer - offsetof(PublicKeyBlob, PublicKey)) + // The key should be the same size as the ECMA key + if (cbKey != sizeof(g_rbNeutralPublicKey)) { return false; } - // The buffer itself looks reasonable, but the public key structure needs to be validated as well - return StrongNameIsValidPublicKey(*pkeyPublicKey); + const PublicKeyBlob *pKeyBlob = reinterpret_cast(pbKey); + return StrongNameIsEcmaKey(*pKeyBlob); } //--------------------------------------------------------------------------------------- @@ -146,30 +148,41 @@ bool StrongNameIsValidPublicKey(const PublicKeyBlob &keyPublicKey) return true; } - //--------------------------------------------------------------------------------------- // -// Determine the number of bytes that a public key blob occupies, including the key portion +// Verify that a public key blob looks like a reasonable public key // // Arguments: -// keyPublicKey - key blob to calculate the size of +// pbBuffer - buffer to verify the format of +// cbBuffer - size of pbBuffer // -DWORD StrongNameSizeOfPublicKey(const PublicKeyBlob &keyPublicKey) +bool StrongNameIsValidPublicKey(_In_reads_(cbBuffer) const BYTE *pbBuffer, DWORD cbBuffer) { CONTRACTL { + PRECONDITION(CheckPointer(pbBuffer)); NOTHROW; GC_NOTRIGGER; } CONTRACTL_END; - return offsetof(PublicKeyBlob, PublicKey) + // Size of the blob header plus - GET_UNALIGNED_VAL32(&keyPublicKey.cbPublicKey); // the number of bytes in the key -} - + // The buffer must be at least as large as the public key structure + if (cbBuffer < sizeof(PublicKeyBlob)) + { + return false; + } + // The buffer must be the same size as the structure header plus the trailing key data + const PublicKeyBlob *pkeyPublicKey = reinterpret_cast(pbBuffer); + if (GET_UNALIGNED_VAL32(&pkeyPublicKey->cbPublicKey) != cbBuffer - offsetof(PublicKeyBlob, PublicKey)) + { + return false; + } + // The buffer itself looks reasonable, but the public key structure needs to be validated as well + return StrongNameIsValidPublicKey(*pkeyPublicKey); +} // Size in bytes of strong name token. #define SN_SIZEOF_TOKEN 8 @@ -277,34 +290,6 @@ HRESULT StrongNameTokenFromPublicKey(BYTE *pbPublicKeyBlob, // [in] pu goto Exit; } - // To compute the correct public key token, we need to make sure the public key blob - // was not padded with extra bytes that CAPI CryptImportKey would've ignored. - // Without this round trip, we would blindly compute the hash over the padded bytes - // which could make finding a public key token collision a significantly easier task - // since an attacker wouldn't need to work hard on generating valid key pairs before hashing. - if (cbPublicKeyBlob <= sizeof(PublicKeyBlob)) { - hr = CORSEC_E_INVALID_PUBLICKEY; - goto Error; - } - - // Check that the blob type is PUBLICKEYBLOB. - pPublicKey = (PublicKeyBlob*) pbPublicKeyBlob; - - if (GET_UNALIGNED_VAL32(&pPublicKey->cbPublicKey) > cbPublicKeyBlob) { - hr = CORSEC_E_INVALID_PUBLICKEY; - goto Error; - } - - if (cbPublicKeyBlob < SN_SIZEOF_KEY(pPublicKey)) { - hr = CORSEC_E_INVALID_PUBLICKEY; - goto Error; - } - - if (*(BYTE*) pPublicKey->PublicKey /* PUBLICKEYSTRUC->bType */ != PUBLICKEYBLOB) { - hr = CORSEC_E_INVALID_PUBLICKEY; - goto Error; - } - // Compute a hash over the public key. sha1.AddData(pbPublicKeyBlob, cbPublicKeyBlob); pHash = sha1.GetHash(); diff --git a/src/coreclr/vm/methodtablebuilder.cpp b/src/coreclr/vm/methodtablebuilder.cpp index 44ddcf546064b..949040ea47006 100644 --- a/src/coreclr/vm/methodtablebuilder.cpp +++ b/src/coreclr/vm/methodtablebuilder.cpp @@ -18,7 +18,6 @@ #include "dllimport.h" #include "fieldmarshaler.h" #include "encee.h" -#include "ecmakey.h" #include "customattribute.h" #include "typestring.h" From 349b811f883f32ac686b6bddec7f574deadd7216 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Fri, 1 Dec 2023 17:14:38 -0800 Subject: [PATCH 02/10] Move PublicKeyBlob back to the header to allow removing the behavior change in ILASM. --- src/coreclr/ilasm/asmman.cpp | 22 +++++++++++++++++++ src/coreclr/ilasm/asmman.hpp | 1 + src/coreclr/ilasm/writer.cpp | 2 +- src/coreclr/inc/strongnameinternal.h | 8 +++++++ src/coreclr/md/runtime/strongnameinternal.cpp | 8 ------- 5 files changed, 32 insertions(+), 9 deletions(-) diff --git a/src/coreclr/ilasm/asmman.cpp b/src/coreclr/ilasm/asmman.cpp index 01bbf4edc994b..4234786baafd9 100644 --- a/src/coreclr/ilasm/asmman.cpp +++ b/src/coreclr/ilasm/asmman.cpp @@ -448,6 +448,27 @@ void AsmMan::EndAssembly() } CloseHandle(hFile); + + // Guess whether we're full or delay signing based on + // whether the blob passed to us looks like a public + // key. (I.e. we may just have copied a full key pair + // into the public key buffer). + if (m_sStrongName.m_cbPublicKey >= sizeof(PublicKeyBlob) && + (offsetof(PublicKeyBlob, PublicKey) + + VAL32(((PublicKeyBlob*)m_sStrongName.m_pbPublicKey)->cbPublicKey)) == m_sStrongName.m_cbPublicKey) + m_sStrongName.m_fFullSign = FALSE; + else + m_sStrongName.m_fFullSign = TRUE; + + // If we really have a key pair, we'll move it into a + // key container so the signing code gets the key pair + // from a consistent place. + if (m_sStrongName.m_fFullSign) + { + report->error("Error: ilasm on CoreCLR does not support full sign.\n"); + m_pCurAsmRef = NULL; + return; + } } } else @@ -464,6 +485,7 @@ void AsmMan::EndAssembly() } m_sStrongName.m_wzKeyContainer = NULL; + m_sStrongName.m_fFullSign = FALSE; m_sStrongName.m_dwPublicKeyAllocated = AsmManStrongName::NotAllocated; } } diff --git a/src/coreclr/ilasm/asmman.hpp b/src/coreclr/ilasm/asmman.hpp index a8dd0516bc3a9..db4765e069418 100644 --- a/src/coreclr/ilasm/asmman.hpp +++ b/src/coreclr/ilasm/asmman.hpp @@ -138,6 +138,7 @@ struct AsmManStrongName BYTE *m_pbPrivateKey; DWORD m_cbPrivateKey; WCHAR *m_wzKeyContainer; + BOOL m_fFullSign; // Where has the memory pointed to by m_pbPublicKey been taken from: AllocationState m_dwPublicKeyAllocated; diff --git a/src/coreclr/ilasm/writer.cpp b/src/coreclr/ilasm/writer.cpp index d971c7f190d9e..6f96b0bd632f1 100644 --- a/src/coreclr/ilasm/writer.cpp +++ b/src/coreclr/ilasm/writer.cpp @@ -1034,7 +1034,7 @@ HRESULT Assembler::CreatePEFile(_In_ __nullterminated WCHAR *pwzOutputFilename) goto exit; } - // CoreCLR ILAsm only supports public signing + // Public-sign by default m_dwComImageFlags |= COMIMAGE_FLAGS_STRONGNAMESIGNED; } diff --git a/src/coreclr/inc/strongnameinternal.h b/src/coreclr/inc/strongnameinternal.h index f0337cc988fd2..a18c16e7d5fd1 100644 --- a/src/coreclr/inc/strongnameinternal.h +++ b/src/coreclr/inc/strongnameinternal.h @@ -7,6 +7,14 @@ #ifndef _STRONGNAME_INTERNAL_H #define _STRONGNAME_INTERNAL_H +// Public key blob binary format. +typedef struct { + unsigned int SigAlgID; // (ALG_ID) signature algorithm used to create the signature + unsigned int HashAlgID; // (ALG_ID) hash algorithm used to create the signature + ULONG cbPublicKey; // length of the key in bytes + BYTE PublicKey[1]; // variable length byte array containing the key value in format output by CryptoAPI +} PublicKeyBlob; + HRESULT StrongNameTokenFromPublicKey(BYTE* pbPublicKeyBlob, // [in] public key blob ULONG cbPublicKeyBlob, BYTE** ppbStrongNameToken, // [out] strong name token diff --git a/src/coreclr/md/runtime/strongnameinternal.cpp b/src/coreclr/md/runtime/strongnameinternal.cpp index f3b9683ac5bf3..2b70129c3ea0c 100644 --- a/src/coreclr/md/runtime/strongnameinternal.cpp +++ b/src/coreclr/md/runtime/strongnameinternal.cpp @@ -19,14 +19,6 @@ #include "thekey.h" #include "ecmakey.h" -// Public key blob binary format. -typedef struct { - unsigned int SigAlgID; // (ALG_ID) signature algorithm used to create the signature - unsigned int HashAlgID; // (ALG_ID) hash algorithm used to create the signature - ULONG cbPublicKey; // length of the key in bytes - BYTE PublicKey[1]; // variable length byte array containing the key value in format output by CryptoAPI -} PublicKeyBlob; - //--------------------------------------------------------------------------------------- // // Determine the number of bytes that a public key blob occupies, including the key portion From 0624c5f38e8c3f1a2125baa454b7bd6a9e9a575d Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Sat, 2 Dec 2023 11:44:04 -0800 Subject: [PATCH 03/10] Remove unused label --- src/coreclr/md/runtime/strongnameinternal.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/coreclr/md/runtime/strongnameinternal.cpp b/src/coreclr/md/runtime/strongnameinternal.cpp index 2b70129c3ea0c..7dac80aa110a2 100644 --- a/src/coreclr/md/runtime/strongnameinternal.cpp +++ b/src/coreclr/md/runtime/strongnameinternal.cpp @@ -296,11 +296,6 @@ HRESULT StrongNameTokenFromPublicKey(BYTE *pbPublicKeyBlob, // [in] pu goto Exit; - Error: - if (*ppbStrongNameToken) { - delete [] *ppbStrongNameToken; - *ppbStrongNameToken = NULL; - } Exit: #else DacNotImpl(); From 2861eab44b21081bcf1ff7adcf6e5c3d71338bfd Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Tue, 5 Dec 2023 10:35:44 -0800 Subject: [PATCH 04/10] Inline the known keys. --- src/coreclr/inc/ecmakey.h | 8 - src/coreclr/inc/strongnameinternal.h | 3 + src/coreclr/inc/thekey.h | 53 --- src/coreclr/md/runtime/strongnameinternal.cpp | 368 ++++++++++-------- src/coreclr/vm/baseassemblyspec.cpp | 5 +- 5 files changed, 209 insertions(+), 228 deletions(-) delete mode 100644 src/coreclr/inc/ecmakey.h delete mode 100644 src/coreclr/inc/thekey.h diff --git a/src/coreclr/inc/ecmakey.h b/src/coreclr/inc/ecmakey.h deleted file mode 100644 index a4ec51be19585..0000000000000 --- a/src/coreclr/inc/ecmakey.h +++ /dev/null @@ -1,8 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -#pragma once - -// The byte values of the ECMA pseudo public key and its token. -const BYTE g_rbNeutralPublicKey[] = { 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0 }; -const BYTE g_rbNeutralPublicKeyToken[] = { 0xb7, 0x7a, 0x5c, 0x56, 0x19, 0x34, 0xe0, 0x89 }; - diff --git a/src/coreclr/inc/strongnameinternal.h b/src/coreclr/inc/strongnameinternal.h index a18c16e7d5fd1..c0932d771b739 100644 --- a/src/coreclr/inc/strongnameinternal.h +++ b/src/coreclr/inc/strongnameinternal.h @@ -7,6 +7,9 @@ #ifndef _STRONGNAME_INTERNAL_H #define _STRONGNAME_INTERNAL_H +extern BYTE const* const g_coreLibPublicKey; +extern const ULONG g_coreLibPublicKeyLen; + // Public key blob binary format. typedef struct { unsigned int SigAlgID; // (ALG_ID) signature algorithm used to create the signature diff --git a/src/coreclr/inc/thekey.h b/src/coreclr/inc/thekey.h deleted file mode 100644 index a972e2ca561da..0000000000000 --- a/src/coreclr/inc/thekey.h +++ /dev/null @@ -1,53 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -#pragma once -// This file allows customization of the strongname key used to replace the ECMA key - -static const BYTE g_rbTheKey[] = -{ -0x00,0x24,0x00,0x00,0x04,0x80,0x00,0x00,0x94,0x00,0x00,0x00,0x06,0x02,0x00,0x00, -0x00,0x24,0x00,0x00,0x52,0x53,0x41,0x31,0x00,0x04,0x00,0x00,0x01,0x00,0x01,0x00, -0x07,0xd1,0xfa,0x57,0xc4,0xae,0xd9,0xf0,0xa3,0x2e,0x84,0xaa,0x0f,0xae,0xfd,0x0d, -0xe9,0xe8,0xfd,0x6a,0xec,0x8f,0x87,0xfb,0x03,0x76,0x6c,0x83,0x4c,0x99,0x92,0x1e, -0xb2,0x3b,0xe7,0x9a,0xd9,0xd5,0xdc,0xc1,0xdd,0x9a,0xd2,0x36,0x13,0x21,0x02,0x90, -0x0b,0x72,0x3c,0xf9,0x80,0x95,0x7f,0xc4,0xe1,0x77,0x10,0x8f,0xc6,0x07,0x77,0x4f, -0x29,0xe8,0x32,0x0e,0x92,0xea,0x05,0xec,0xe4,0xe8,0x21,0xc0,0xa5,0xef,0xe8,0xf1, -0x64,0x5c,0x4c,0x0c,0x93,0xc1,0xab,0x99,0x28,0x5d,0x62,0x2c,0xaa,0x65,0x2c,0x1d, -0xfa,0xd6,0x3d,0x74,0x5d,0x6f,0x2d,0xe5,0xf1,0x7e,0x5e,0xaf,0x0f,0xc4,0x96,0x3d, -0x26,0x1c,0x8a,0x12,0x43,0x65,0x18,0x20,0x6d,0xc0,0x93,0x34,0x4d,0x5a,0xd2,0x93 -}; - -static const BYTE g_rbTheKeyToken[] = {0xb0,0x3f,0x5f,0x7f,0x11,0xd5,0x0a,0x3a}; - - -static const BYTE g_rbTheSilverlightPlatformKey[] = -{ -0x00,0x24,0x00,0x00,0x04,0x80,0x00,0x00,0x94,0x00,0x00,0x00,0x06,0x02,0x00,0x00, -0x00,0x24,0x00,0x00,0x52,0x53,0x41,0x31,0x00,0x04,0x00,0x00,0x01,0x00,0x01,0x00, -0x8d,0x56,0xc7,0x6f,0x9e,0x86,0x49,0x38,0x30,0x49,0xf3,0x83,0xc4,0x4b,0xe0,0xec, -0x20,0x41,0x81,0x82,0x2a,0x6c,0x31,0xcf,0x5e,0xb7,0xef,0x48,0x69,0x44,0xd0,0x32, -0x18,0x8e,0xa1,0xd3,0x92,0x07,0x63,0x71,0x2c,0xcb,0x12,0xd7,0x5f,0xb7,0x7e,0x98, -0x11,0x14,0x9e,0x61,0x48,0xe5,0xd3,0x2f,0xba,0xab,0x37,0x61,0x1c,0x18,0x78,0xdd, -0xc1,0x9e,0x20,0xef,0x13,0x5d,0x0c,0xb2,0xcf,0xf2,0xbf,0xec,0x3d,0x11,0x58,0x10, -0xc3,0xd9,0x06,0x96,0x38,0xfe,0x4b,0xe2,0x15,0xdb,0xf7,0x95,0x86,0x19,0x20,0xe5, -0xab,0x6f,0x7d,0xb2,0xe2,0xce,0xef,0x13,0x6a,0xc2,0x3d,0x5d,0xd2,0xbf,0x03,0x17, -0x00,0xae,0xc2,0x32,0xf6,0xc6,0xb1,0xc7,0x85,0xb4,0x30,0x5c,0x12,0x3b,0x37,0xab -}; - -static const BYTE g_rbTheSilverlightPlatformKeyToken[] = {0x7c,0xec,0x85,0xd7,0xbe,0xa7,0x79,0x8e}; - -static const BYTE g_rbTheSilverlightKey[] = -{ -0x00,0x24,0x00,0x00,0x04,0x80,0x00,0x00,0x94,0x00,0x00,0x00,0x06,0x02,0x00,0x00, -0x00,0x24,0x00,0x00,0x52,0x53,0x41,0x31,0x00,0x04,0x00,0x00,0x01,0x00,0x01,0x00, -0xb5,0xfc,0x90,0xe7,0x02,0x7f,0x67,0x87,0x1e,0x77,0x3a,0x8f,0xde,0x89,0x38,0xc8, -0x1d,0xd4,0x02,0xba,0x65,0xb9,0x20,0x1d,0x60,0x59,0x3e,0x96,0xc4,0x92,0x65,0x1e, -0x88,0x9c,0xc1,0x3f,0x14,0x15,0xeb,0xb5,0x3f,0xac,0x11,0x31,0xae,0x0b,0xd3,0x33, -0xc5,0xee,0x60,0x21,0x67,0x2d,0x97,0x18,0xea,0x31,0xa8,0xae,0xbd,0x0d,0xa0,0x07, -0x2f,0x25,0xd8,0x7d,0xba,0x6f,0xc9,0x0f,0xfd,0x59,0x8e,0xd4,0xda,0x35,0xe4,0x4c, -0x39,0x8c,0x45,0x43,0x07,0xe8,0xe3,0x3b,0x84,0x26,0x14,0x3d,0xae,0xc9,0xf5,0x96, -0x83,0x6f,0x97,0xc8,0xf7,0x47,0x50,0xe5,0x97,0x5c,0x64,0xe2,0x18,0x9f,0x45,0xde, -0xf4,0x6b,0x2a,0x2b,0x12,0x47,0xad,0xc3,0x65,0x2b,0xf5,0xc3,0x08,0x05,0x5d,0xa9 -}; - -static const BYTE g_rbTheSilverlightKeyToken[] = {0x31,0xBF,0x38,0x56,0xAD,0x36,0x4E,0x35}; diff --git a/src/coreclr/md/runtime/strongnameinternal.cpp b/src/coreclr/md/runtime/strongnameinternal.cpp index 7dac80aa110a2..32203fc4ec78b 100644 --- a/src/coreclr/md/runtime/strongnameinternal.cpp +++ b/src/coreclr/md/runtime/strongnameinternal.cpp @@ -8,174 +8,226 @@ #include "strongnameinternal.h" #include "sha1.h" -// We allow a special abbreviated form of the Microsoft public key (16 bytes -// long: 0 for both alg ids, 4 for key length and 4 bytes of 0 for the key -// itself). This allows us to build references to system libraries that are -// platform neutral (so a 3rd party can build SPCL replacements). The -// special zero PK is just shorthand for the local runtime's real system PK, -// which is always used to perform the signature verification, so no security -// hole is opened by this. Therefore we need to store a copy of the real PK (for -// this platform) here. -#include "thekey.h" -#include "ecmakey.h" - -//--------------------------------------------------------------------------------------- -// -// Determine the number of bytes that a public key blob occupies, including the key portion -// -// Arguments: -// keyPublicKey - key blob to calculate the size of -// +// Common keys used by libraries we ship are included here. -DWORD StrongNameSizeOfPublicKey(const PublicKeyBlob &keyPublicKey) +namespace { - CONTRACTL + // The byte values of the ECMA pseudo public key and its token. + const BYTE g_rbNeutralPublicKey[] = { 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0 }; + const BYTE g_rbNeutralPublicKeyToken[] = { 0xb7, 0x7a, 0x5c, 0x56, 0x19, 0x34, 0xe0, 0x89 }; + + // The byte values of the real public keys and their corresponding tokens + // for assemblies we ship. + // These blobs allow us to skip the token calculation for our assemblies. + static const BYTE g_rbMicrosoftKey[] = { - NOTHROW; - GC_NOTRIGGER; - } - CONTRACTL_END; - - return offsetof(PublicKeyBlob, PublicKey) + // Size of the blob header plus - GET_UNALIGNED_VAL32(&keyPublicKey.cbPublicKey); // the number of bytes in the key -} - -//--------------------------------------------------------------------------------------- -// -// Check to see if a public key blob is the ECMA public key blob -// -// Arguments: -// keyPublicKey - Key to check to see if it matches the ECMA key -// - -bool StrongNameIsEcmaKey(const PublicKeyBlob &keyPublicKey) -{ - CONTRACTL + 0x00,0x24,0x00,0x00,0x04,0x80,0x00,0x00,0x94,0x00,0x00,0x00,0x06,0x02,0x00,0x00, + 0x00,0x24,0x00,0x00,0x52,0x53,0x41,0x31,0x00,0x04,0x00,0x00,0x01,0x00,0x01,0x00, + 0x07,0xd1,0xfa,0x57,0xc4,0xae,0xd9,0xf0,0xa3,0x2e,0x84,0xaa,0x0f,0xae,0xfd,0x0d, + 0xe9,0xe8,0xfd,0x6a,0xec,0x8f,0x87,0xfb,0x03,0x76,0x6c,0x83,0x4c,0x99,0x92,0x1e, + 0xb2,0x3b,0xe7,0x9a,0xd9,0xd5,0xdc,0xc1,0xdd,0x9a,0xd2,0x36,0x13,0x21,0x02,0x90, + 0x0b,0x72,0x3c,0xf9,0x80,0x95,0x7f,0xc4,0xe1,0x77,0x10,0x8f,0xc6,0x07,0x77,0x4f, + 0x29,0xe8,0x32,0x0e,0x92,0xea,0x05,0xec,0xe4,0xe8,0x21,0xc0,0xa5,0xef,0xe8,0xf1, + 0x64,0x5c,0x4c,0x0c,0x93,0xc1,0xab,0x99,0x28,0x5d,0x62,0x2c,0xaa,0x65,0x2c,0x1d, + 0xfa,0xd6,0x3d,0x74,0x5d,0x6f,0x2d,0xe5,0xf1,0x7e,0x5e,0xaf,0x0f,0xc4,0x96,0x3d, + 0x26,0x1c,0x8a,0x12,0x43,0x65,0x18,0x20,0x6d,0xc0,0x93,0x34,0x4d,0x5a,0xd2,0x93 + }; + + static const BYTE g_rbMicrosoftKeyToken[] = {0xb0,0x3f,0x5f,0x7f,0x11,0xd5,0x0a,0x3a}; + + static const BYTE g_rbTheSilverlightPlatformKey[] = { - NOTHROW; - GC_NOTRIGGER; - } - CONTRACTL_END; - - return StrongNameSizeOfPublicKey(keyPublicKey) == sizeof(g_rbNeutralPublicKey) && - memcmp(reinterpret_cast(&keyPublicKey), g_rbNeutralPublicKey, sizeof(g_rbNeutralPublicKey)) == 0; -} - -//--------------------------------------------------------------------------------------- -// -// Check to see if a public key blob is the ECMA public key blob -// -// Arguments: -// pbKey - public key blob to check -// cbKey - size in bytes of pbKey -// - -bool StrongNameIsEcmaKey(_In_reads_(cbKey) const BYTE *pbKey, DWORD cbKey) -{ - CONTRACTL + 0x00,0x24,0x00,0x00,0x04,0x80,0x00,0x00,0x94,0x00,0x00,0x00,0x06,0x02,0x00,0x00, + 0x00,0x24,0x00,0x00,0x52,0x53,0x41,0x31,0x00,0x04,0x00,0x00,0x01,0x00,0x01,0x00, + 0x8d,0x56,0xc7,0x6f,0x9e,0x86,0x49,0x38,0x30,0x49,0xf3,0x83,0xc4,0x4b,0xe0,0xec, + 0x20,0x41,0x81,0x82,0x2a,0x6c,0x31,0xcf,0x5e,0xb7,0xef,0x48,0x69,0x44,0xd0,0x32, + 0x18,0x8e,0xa1,0xd3,0x92,0x07,0x63,0x71,0x2c,0xcb,0x12,0xd7,0x5f,0xb7,0x7e,0x98, + 0x11,0x14,0x9e,0x61,0x48,0xe5,0xd3,0x2f,0xba,0xab,0x37,0x61,0x1c,0x18,0x78,0xdd, + 0xc1,0x9e,0x20,0xef,0x13,0x5d,0x0c,0xb2,0xcf,0xf2,0xbf,0xec,0x3d,0x11,0x58,0x10, + 0xc3,0xd9,0x06,0x96,0x38,0xfe,0x4b,0xe2,0x15,0xdb,0xf7,0x95,0x86,0x19,0x20,0xe5, + 0xab,0x6f,0x7d,0xb2,0xe2,0xce,0xef,0x13,0x6a,0xc2,0x3d,0x5d,0xd2,0xbf,0x03,0x17, + 0x00,0xae,0xc2,0x32,0xf6,0xc6,0xb1,0xc7,0x85,0xb4,0x30,0x5c,0x12,0x3b,0x37,0xab + }; + + static const BYTE g_rbTheSilverlightPlatformKeyToken[] = {0x7c,0xec,0x85,0xd7,0xbe,0xa7,0x79,0x8e}; + + static const BYTE g_rbTheSilverlightKey[] = { - NOTHROW; - GC_NOTRIGGER; - } - CONTRACTL_END; - - // The key should be the same size as the ECMA key - if (cbKey != sizeof(g_rbNeutralPublicKey)) + 0x00,0x24,0x00,0x00,0x04,0x80,0x00,0x00,0x94,0x00,0x00,0x00,0x06,0x02,0x00,0x00, + 0x00,0x24,0x00,0x00,0x52,0x53,0x41,0x31,0x00,0x04,0x00,0x00,0x01,0x00,0x01,0x00, + 0xb5,0xfc,0x90,0xe7,0x02,0x7f,0x67,0x87,0x1e,0x77,0x3a,0x8f,0xde,0x89,0x38,0xc8, + 0x1d,0xd4,0x02,0xba,0x65,0xb9,0x20,0x1d,0x60,0x59,0x3e,0x96,0xc4,0x92,0x65,0x1e, + 0x88,0x9c,0xc1,0x3f,0x14,0x15,0xeb,0xb5,0x3f,0xac,0x11,0x31,0xae,0x0b,0xd3,0x33, + 0xc5,0xee,0x60,0x21,0x67,0x2d,0x97,0x18,0xea,0x31,0xa8,0xae,0xbd,0x0d,0xa0,0x07, + 0x2f,0x25,0xd8,0x7d,0xba,0x6f,0xc9,0x0f,0xfd,0x59,0x8e,0xd4,0xda,0x35,0xe4,0x4c, + 0x39,0x8c,0x45,0x43,0x07,0xe8,0xe3,0x3b,0x84,0x26,0x14,0x3d,0xae,0xc9,0xf5,0x96, + 0x83,0x6f,0x97,0xc8,0xf7,0x47,0x50,0xe5,0x97,0x5c,0x64,0xe2,0x18,0x9f,0x45,0xde, + 0xf4,0x6b,0x2a,0x2b,0x12,0x47,0xad,0xc3,0x65,0x2b,0xf5,0xc3,0x08,0x05,0x5d,0xa9 + }; + + static const BYTE g_rbTheSilverlightKeyToken[] = {0x31,0xBF,0x38,0x56,0xAD,0x36,0x4E,0x35}; + + //--------------------------------------------------------------------------------------- + // + // Determine the number of bytes that a public key blob occupies, including the key portion + // + // Arguments: + // keyPublicKey - key blob to calculate the size of + // + + DWORD StrongNameSizeOfPublicKey(const PublicKeyBlob &keyPublicKey) { - return false; + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + return offsetof(PublicKeyBlob, PublicKey) + // Size of the blob header plus + GET_UNALIGNED_VAL32(&keyPublicKey.cbPublicKey); // the number of bytes in the key } - const PublicKeyBlob *pKeyBlob = reinterpret_cast(pbKey); - return StrongNameIsEcmaKey(*pKeyBlob); -} - -//--------------------------------------------------------------------------------------- -// -// Verify that a public key blob looks like a reasonable public key. -// -// Arguments: -// keyPublicKey - key blob to verify -// -// Notes: -// This can be a very expensive operation, since it involves importing keys. -// - -bool StrongNameIsValidPublicKey(const PublicKeyBlob &keyPublicKey) -{ - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - } - CONTRACTL_END; + //--------------------------------------------------------------------------------------- + // + // Check to see if a public key blob is the ECMA public key blob + // + // Arguments: + // keyPublicKey - Key to check to see if it matches the ECMA key + // - // The ECMA key doesn't look like a valid key so it will fail the below checks. If we were passed that - // key, then we can skip them - if (StrongNameIsEcmaKey(keyPublicKey)) + bool StrongNameIsEcmaKey(const PublicKeyBlob &keyPublicKey) { - return true; + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + return StrongNameSizeOfPublicKey(keyPublicKey) == sizeof(g_rbNeutralPublicKey) && + memcmp(reinterpret_cast(&keyPublicKey), g_rbNeutralPublicKey, sizeof(g_rbNeutralPublicKey)) == 0; } - // If a hash algorithm is specified, it must be a sensible value - bool fHashAlgorithmValid = GET_ALG_CLASS(GET_UNALIGNED_VAL32(&keyPublicKey.HashAlgID)) == ALG_CLASS_HASH && - GET_ALG_SID(GET_UNALIGNED_VAL32(&keyPublicKey.HashAlgID)) >= ALG_SID_SHA1; - if (keyPublicKey.HashAlgID != 0 && !fHashAlgorithmValid) - { - return false; - } + //--------------------------------------------------------------------------------------- + // + // Check to see if a public key blob is the ECMA public key blob + // + // Arguments: + // pbKey - public key blob to check + // cbKey - size in bytes of pbKey + // - // If a signature algorithm is specified, it must be a sensible value - bool fSignatureAlgorithmValid = GET_ALG_CLASS(GET_UNALIGNED_VAL32(&keyPublicKey.SigAlgID)) == ALG_CLASS_SIGNATURE; - if (keyPublicKey.SigAlgID != 0 && !fSignatureAlgorithmValid) + bool StrongNameIsEcmaKey(_In_reads_(cbKey) const BYTE *pbKey, DWORD cbKey) { - return false; + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + // The key should be the same size as the ECMA key + if (cbKey != sizeof(g_rbNeutralPublicKey)) + { + return false; + } + + const PublicKeyBlob *pKeyBlob = reinterpret_cast(pbKey); + return StrongNameIsEcmaKey(*pKeyBlob); } - // The key blob must indicate that it is a PUBLICKEYBLOB - if (keyPublicKey.PublicKey[0] != PUBLICKEYBLOB) + //--------------------------------------------------------------------------------------- + // + // Verify that a public key blob looks like a reasonable public key. + // + // Arguments: + // keyPublicKey - key blob to verify + // + // Notes: + // This can be a very expensive operation, since it involves importing keys. + // + + bool StrongNameIsValidPublicKey(const PublicKeyBlob &keyPublicKey) { - return false; - } - - return true; -} + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + // The ECMA key doesn't look like a valid key so it will fail the below checks. If we were passed that + // key, then we can skip them + if (StrongNameIsEcmaKey(keyPublicKey)) + { + return true; + } + + // If a hash algorithm is specified, it must be a sensible value + bool fHashAlgorithmValid = GET_ALG_CLASS(GET_UNALIGNED_VAL32(&keyPublicKey.HashAlgID)) == ALG_CLASS_HASH && + GET_ALG_SID(GET_UNALIGNED_VAL32(&keyPublicKey.HashAlgID)) >= ALG_SID_SHA1; + if (keyPublicKey.HashAlgID != 0 && !fHashAlgorithmValid) + { + return false; + } + + // If a signature algorithm is specified, it must be a sensible value + bool fSignatureAlgorithmValid = GET_ALG_CLASS(GET_UNALIGNED_VAL32(&keyPublicKey.SigAlgID)) == ALG_CLASS_SIGNATURE; + if (keyPublicKey.SigAlgID != 0 && !fSignatureAlgorithmValid) + { + return false; + } + + // The key blob must indicate that it is a PUBLICKEYBLOB + if (keyPublicKey.PublicKey[0] != PUBLICKEYBLOB) + { + return false; + } -//--------------------------------------------------------------------------------------- -// -// Verify that a public key blob looks like a reasonable public key -// -// Arguments: -// pbBuffer - buffer to verify the format of -// cbBuffer - size of pbBuffer -// - -bool StrongNameIsValidPublicKey(_In_reads_(cbBuffer) const BYTE *pbBuffer, DWORD cbBuffer) -{ - CONTRACTL - { - PRECONDITION(CheckPointer(pbBuffer)); - NOTHROW; - GC_NOTRIGGER; + return true; } - CONTRACTL_END; - // The buffer must be at least as large as the public key structure - if (cbBuffer < sizeof(PublicKeyBlob)) - { - return false; - } + //--------------------------------------------------------------------------------------- + // + // Verify that a public key blob looks like a reasonable public key + // + // Arguments: + // pbBuffer - buffer to verify the format of + // cbBuffer - size of pbBuffer + // - // The buffer must be the same size as the structure header plus the trailing key data - const PublicKeyBlob *pkeyPublicKey = reinterpret_cast(pbBuffer); - if (GET_UNALIGNED_VAL32(&pkeyPublicKey->cbPublicKey) != cbBuffer - offsetof(PublicKeyBlob, PublicKey)) + bool StrongNameIsValidPublicKey(_In_reads_(cbBuffer) const BYTE *pbBuffer, DWORD cbBuffer) { - return false; + CONTRACTL + { + PRECONDITION(CheckPointer(pbBuffer)); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + // The buffer must be at least as large as the public key structure + if (cbBuffer < sizeof(PublicKeyBlob)) + { + return false; + } + + // The buffer must be the same size as the structure header plus the trailing key data + const PublicKeyBlob *pkeyPublicKey = reinterpret_cast(pbBuffer); + if (GET_UNALIGNED_VAL32(&pkeyPublicKey->cbPublicKey) != cbBuffer - offsetof(PublicKeyBlob, PublicKey)) + { + return false; + } + + // The buffer itself looks reasonable, but the public key structure needs to be validated as well + return StrongNameIsValidPublicKey(*pkeyPublicKey); } - - // The buffer itself looks reasonable, but the public key structure needs to be validated as well - return StrongNameIsValidPublicKey(*pkeyPublicKey); } +BYTE const* const g_coreLibPublicKey = g_rbTheSilverlightPlatformKey; +const ULONG g_coreLibPublicKeyLen = ARRAY_SIZE(g_rbTheSilverlightPlatformKey); + // Size in bytes of strong name token. #define SN_SIZEOF_TOKEN 8 @@ -183,30 +235,18 @@ bool StrongNameIsValidPublicKey(_In_reads_(cbBuffer) const BYTE *pbBuffer, DWORD // portion. #define SN_SIZEOF_KEY(_pKeyBlob) (offsetof(PublicKeyBlob, PublicKey) + GET_UNALIGNED_VAL32(&(_pKeyBlob)->cbPublicKey)) -// We allow a special abbreviated form of the Microsoft public key (16 bytes -// long: 0 for both alg ids, 4 for key length and 4 bytes of 0 for the key -// itself). This allows us to build references to system libraries that are -// platform neutral (so a 3rd party can build SPCL replacements). The -// special zero PK is just shorthand for the local runtime's real system PK, -// which is always used to perform the signature verification, so no security -// hole is opened by this. Therefore we need to store a copy of the real PK (for -// this platform) here. - -// the actual definition of the microsoft key is in separate file to allow custom keys -#include "thekey.h" - -#define SN_THE_KEY() ((PublicKeyBlob*)g_rbTheKey) -#define SN_SIZEOF_THE_KEY() sizeof(g_rbTheKey) +#define SN_MICROSOFT_KEY() ((PublicKeyBlob*)g_rbMicrosoftKey) +#define SN_SIZEOF_MICROSOFT_KEY() sizeof(g_rbMicrosoftKey) -#define SN_THE_KEYTOKEN() ((PublicKeyBlob*)g_rbTheKeyToken) +#define SN_MICROSOFT_KEYTOKEN() ((PublicKeyBlob*)g_rbMicrosoftKeyToken) // Determine if the given public key blob is the neutral key. #define SN_IS_NEUTRAL_KEY(_pk) (SN_SIZEOF_KEY((PublicKeyBlob*)(_pk)) == sizeof(g_rbNeutralPublicKey) && \ memcmp((_pk), g_rbNeutralPublicKey, sizeof(g_rbNeutralPublicKey)) == 0) -#define SN_IS_THE_KEY(_pk) (SN_SIZEOF_KEY((PublicKeyBlob*)(_pk)) == sizeof(g_rbTheKey) && \ - memcmp((_pk), g_rbTheKey, sizeof(g_rbTheKey)) == 0) +#define SN_IS_MICROSOFT_KEY(_pk) (SN_SIZEOF_KEY((PublicKeyBlob*)(_pk)) == sizeof(g_rbMicrosoftKey) && \ + memcmp((_pk), g_rbMicrosoftKey, sizeof(g_rbMicrosoftKey)) == 0) // Silverlight platform key @@ -224,7 +264,7 @@ bool StrongNameIsValidPublicKey(_In_reads_(cbBuffer) const BYTE *pbBuffer, DWORD // Free buffer allocated by routines below. VOID StrongNameFreeBuffer(BYTE *pbMemory) // [in] address of memory to free { - if (pbMemory != (BYTE*)SN_THE_KEY() && pbMemory != g_rbNeutralPublicKey) + if (pbMemory != (BYTE*)SN_MICROSOFT_KEY() && pbMemory != g_rbNeutralPublicKey) delete [] pbMemory; } @@ -264,9 +304,9 @@ HRESULT StrongNameTokenFromPublicKey(BYTE *pbPublicKeyBlob, // [in] pu memcpy_s(*ppbStrongNameToken, *pcbStrongNameToken, g_rbNeutralPublicKeyToken, SN_SIZEOF_TOKEN); goto Exit; } - if (cbPublicKeyBlob == SN_SIZEOF_THE_KEY() && - memcmp(pbPublicKeyBlob, SN_THE_KEY(), cbPublicKeyBlob) == 0) { - memcpy_s(*ppbStrongNameToken, *pcbStrongNameToken, SN_THE_KEYTOKEN(), SN_SIZEOF_TOKEN); + if (cbPublicKeyBlob == SN_SIZEOF_MICROSOFT_KEY() && + memcmp(pbPublicKeyBlob, SN_MICROSOFT_KEY(), cbPublicKeyBlob) == 0) { + memcpy_s(*ppbStrongNameToken, *pcbStrongNameToken, SN_MICROSOFT_KEYTOKEN(), SN_SIZEOF_TOKEN); goto Exit; } diff --git a/src/coreclr/vm/baseassemblyspec.cpp b/src/coreclr/vm/baseassemblyspec.cpp index fbc0afad966c0..31d10243480f2 100644 --- a/src/coreclr/vm/baseassemblyspec.cpp +++ b/src/coreclr/vm/baseassemblyspec.cpp @@ -11,7 +11,6 @@ // ============================================================ #include "common.h" -#include "thekey.h" #include "strongnameinternal.h" #include "strongnameholders.h" @@ -72,12 +71,12 @@ BOOL BaseAssemblySpec::IsCoreLibSatellite() const size_t iNameLen = strlen(m_pAssemblyName); // we allow name to be of the form System.Private.CoreLib.resources.dll only - BOOL r = ( (m_cbPublicKeyOrToken == sizeof(CORELIB_PUBLICKEY)) && + BOOL r = ( (m_cbPublicKeyOrToken == sizeof(g_coreLibPublicKey)) && (iNameLen >= CoreLibSatelliteNameLen) && (!SString::_strnicmp(m_pAssemblyName, g_psBaseLibrarySatelliteAssemblyName, CoreLibSatelliteNameLen)) && ( (iNameLen == CoreLibSatelliteNameLen) || (m_pAssemblyName[CoreLibSatelliteNameLen] == ',') ) ); - r = r && ( memcmp(m_pbPublicKeyOrToken,CORELIB_PUBLICKEY,sizeof(CORELIB_PUBLICKEY)) == 0); + r = r && ( memcmp(m_pbPublicKeyOrToken, g_coreLibPublicKey, g_coreLibPublicKeyLen) == 0); return r; } From e18db4ecc137ad5266dbdeb9b84ca6e7cad9d559 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Tue, 5 Dec 2023 10:54:30 -0800 Subject: [PATCH 05/10] Remove allocations from StrongNameTokenFromPublicKey --- src/coreclr/binder/utils.cpp | 9 ++-- src/coreclr/inc/strongnameholders.h | 23 ---------- src/coreclr/inc/strongnameinternal.h | 9 ++-- src/coreclr/md/compiler/importhelper.cpp | 42 ++++++------------- src/coreclr/md/runtime/strongnameinternal.cpp | 32 ++++---------- src/coreclr/vm/assemblyspec.cpp | 21 ++++------ src/coreclr/vm/baseassemblyspec.cpp | 13 +++--- src/coreclr/vm/coreassemblyspec.cpp | 9 ++-- 8 files changed, 44 insertions(+), 114 deletions(-) delete mode 100644 src/coreclr/inc/strongnameholders.h diff --git a/src/coreclr/binder/utils.cpp b/src/coreclr/binder/utils.cpp index edd1e0026b74d..a40608271f46f 100644 --- a/src/coreclr/binder/utils.cpp +++ b/src/coreclr/binder/utils.cpp @@ -54,18 +54,15 @@ namespace BINDER_SPACE const BYTE *pByteKey = publicKeyBLOB; DWORD dwKeyLen = publicKeyBLOB.GetSize(); - BYTE *pByteToken = NULL; - DWORD dwTokenLen = 0; + BYTE pByteToken[SN_SIZEOF_TOKEN]; IF_FAIL_GO(StrongNameTokenFromPublicKey( const_cast(pByteKey), dwKeyLen, - &pByteToken, - &dwTokenLen)); + pByteToken)); _ASSERTE(pByteToken != NULL); - publicKeyTokenBLOB.Set(pByteToken, dwTokenLen); - StrongNameFreeBuffer(pByteToken); + publicKeyTokenBLOB.Set(pByteToken, SN_SIZEOF_TOKEN); Exit: return hr; diff --git a/src/coreclr/inc/strongnameholders.h b/src/coreclr/inc/strongnameholders.h deleted file mode 100644 index 6d687c0f321ff..0000000000000 --- a/src/coreclr/inc/strongnameholders.h +++ /dev/null @@ -1,23 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#ifndef __STRONGNAME_HOLDERS_H__ -#define __STRONGNAME_HOLDERS_H__ - -#include -#include - -// -// Holder classes for types returned from and used in strong name APIs -// - -// Holder for any memory allocated by the strong name APIs -template -void VoidStrongNameFreeBuffer(_In_ T *pBuffer) -{ - StrongNameFreeBuffer(reinterpret_cast(pBuffer)); -} -template -using StrongNameBufferHolder = SpecializedWrapper<_TYPE, VoidStrongNameFreeBuffer<_TYPE>>; - -#endif // !__STRONGNAME_HOLDERS_H__ diff --git a/src/coreclr/inc/strongnameinternal.h b/src/coreclr/inc/strongnameinternal.h index c0932d771b739..a478592f561ca 100644 --- a/src/coreclr/inc/strongnameinternal.h +++ b/src/coreclr/inc/strongnameinternal.h @@ -18,11 +18,12 @@ typedef struct { BYTE PublicKey[1]; // variable length byte array containing the key value in format output by CryptoAPI } PublicKeyBlob; +// Number of bytes for a strong name token. +constexpr ULONG SN_SIZEOF_TOKEN = 8; + HRESULT StrongNameTokenFromPublicKey(BYTE* pbPublicKeyBlob, // [in] public key blob ULONG cbPublicKeyBlob, - BYTE** ppbStrongNameToken, // [out] strong name token - ULONG* pcbStrongNameToken); - -VOID StrongNameFreeBuffer(BYTE* pbMemory); + BYTE(&tokenBuffer)[SN_SIZEOF_TOKEN] // [out] strong name token +); #endif // !_STRONGNAME_INTERNAL_H diff --git a/src/coreclr/md/compiler/importhelper.cpp b/src/coreclr/md/compiler/importhelper.cpp index dc16bdac2f72d..2c873c5a50723 100644 --- a/src/coreclr/md/compiler/importhelper.cpp +++ b/src/coreclr/md/compiler/importhelper.cpp @@ -1313,6 +1313,7 @@ HRESULT ImportHelper::FindAssemblyRef( const void *pbTmp; // Temp blob. ULONG cbTmp; // Temp byte count. DWORD dwTmp; // Temp flags. + const BYTE tokenBuffer[SN_SIZEOF_TOKEN]; // Local buffer for token version of public key. const void *pbToken = NULL; // Token version of public key. ULONG cbToken = 0; // Count of bytes in token. #if !defined(FEATURE_METADATA_EMIT_IN_DEBUGGER) || defined(DACCESS_COMPILE) @@ -1392,13 +1393,12 @@ HRESULT ImportHelper::FindAssemblyRef( #if defined(FEATURE_METADATA_EMIT_IN_DEBUGGER) && !defined(DACCESS_COMPILE) return E_FAIL; #else //!FEATURE_METADATA_EMIT_IN_DEBUGGER || DACCESS_COMPILE + const BYTE tmpTokenBuffer[SN_SIZEOF_TOKEN]; // Need to compress target public key to see if it matches. IfFailRet(StrongNameTokenFromPublicKey((BYTE*)pbTmp, cbTmp, - (BYTE**)&pbTmpToken, - &cbTmpToken)); - fMatch = cbTmpToken == cbPublicKeyOrToken && !memcmp(pbTmpToken, pbPublicKeyOrToken, cbTmpToken); - StrongNameFreeBuffer((BYTE*)pbTmpToken); + tmpTokenBuffer)); + fMatch = SN_SIZEOF_TOKEN == cbPublicKeyOrToken && !memcmp(pbTmpToken, pbPublicKeyOrToken, SN_SIZEOF_TOKEN); if (!fMatch) continue; #endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER || DACCESS_COMPILE @@ -1414,8 +1414,9 @@ HRESULT ImportHelper::FindAssemblyRef( #else //!FEATURE_METADATA_EMIT_IN_DEBUGGER || DACCESS_COMPILE IfFailRet(StrongNameTokenFromPublicKey((BYTE*)pbPublicKeyOrToken, cbPublicKeyOrToken, - (BYTE**)&pbToken, - &cbToken)); + tokenBuffer)); + pbToken = tokenBuffer; + cbToken = SN_SIZEOF_TOKEN; #endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER || DACCESS_COMPILE } if (cbTmp != cbToken || memcmp(pbTmp, pbToken, cbToken)) @@ -1423,21 +1424,9 @@ HRESULT ImportHelper::FindAssemblyRef( } } - if (pbToken && IsAfPublicKey(dwFlags)) - { -#if !defined(FEATURE_METADATA_EMIT_IN_DEBUGGER) || defined(DACCESS_COMPILE) - StrongNameFreeBuffer((BYTE*)pbToken); -#endif - } *pmar = TokenFromRid(i, mdtAssemblyRef); return S_OK; } - if (pbToken && IsAfPublicKey(dwFlags)) - { -#if !defined(FEATURE_METADATA_EMIT_IN_DEBUGGER) || defined(DACCESS_COMPILE) - StrongNameFreeBuffer((BYTE*)pbToken); -#endif - } return CLDB_E_RECORD_NOTFOUND; } // ImportHelper::FindAssemblyRef @@ -3186,8 +3175,7 @@ ImportHelper::CreateAssemblyRefFromAssembly( LPCUTF8 szLocale; mdAssemblyRef tkAssemRef; HRESULT hr = S_OK; - const void *pbToken = NULL; - ULONG cbToken = 0; + BYTE pbToken[SN_SIZEOF_TOKEN]; ULONG i; // Set output to Nil. @@ -3206,8 +3194,7 @@ ImportHelper::CreateAssemblyRefFromAssembly( dwFlags &= ~afPublicKey; IfFailGo(StrongNameTokenFromPublicKey((BYTE*)pbPublicKey, cbPublicKey, - (BYTE**)&pbToken, - &cbToken)); + pbToken)); } else _ASSERTE(!IsAfPublicKey(dwFlags)); @@ -3225,7 +3212,7 @@ ImportHelper::CreateAssemblyRefFromAssembly( // See if the AssemblyRef already exists in the emit scope. hr = FindAssemblyRef(pMiniMdEmit, szName, szLocale, pbToken, - cbToken, usMajorVersion, usMinorVersion, + SN_SIZEOF_TOKEN, usMajorVersion, usMinorVersion, usBuildNumber, usRevisionNumber, dwFlags, &tkAssemRef); if (hr == CLDB_E_RECORD_NOTFOUND) @@ -3261,8 +3248,6 @@ ImportHelper::CreateAssemblyRefFromAssembly( *ptkAssemblyRef = tkAssemRef; } ErrExit: - if (pbToken) - StrongNameFreeBuffer((BYTE*)pbToken); return hr; #endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER } // ImportHelper::CreateAssemblyRefFromAssembly @@ -3341,17 +3326,16 @@ HRESULT ImportHelper::CompareAssemblyRefToAssembly( // S_OK, S_FALSE or error memcmp(pbPublicKeyOrToken1, pbPublicKey2, cbPublicKeyOrToken1))) return S_FALSE; + BYTE token[SN_SIZEOF_TOKEN]; + // Otherwise we need to compress the def public key into a token. IfFailRet(StrongNameTokenFromPublicKey((BYTE*)pbPublicKey2, cbPublicKey2, - (BYTE**)&pbToken, - &cbToken)); + token)); fMatch = cbPublicKeyOrToken1 == cbToken && !memcmp(pbPublicKeyOrToken1, pbToken, cbPublicKeyOrToken1); - StrongNameFreeBuffer((BYTE*)pbToken); - if (!fMatch) return S_FALSE; } diff --git a/src/coreclr/md/runtime/strongnameinternal.cpp b/src/coreclr/md/runtime/strongnameinternal.cpp index 32203fc4ec78b..fc6625d5a7452 100644 --- a/src/coreclr/md/runtime/strongnameinternal.cpp +++ b/src/coreclr/md/runtime/strongnameinternal.cpp @@ -228,9 +228,6 @@ namespace BYTE const* const g_coreLibPublicKey = g_rbTheSilverlightPlatformKey; const ULONG g_coreLibPublicKeyLen = ARRAY_SIZE(g_rbTheSilverlightPlatformKey); -// Size in bytes of strong name token. -#define SN_SIZEOF_TOKEN 8 - // Determine the size of a PublicKeyBlob structure given the size of the key // portion. #define SN_SIZEOF_KEY(_pKeyBlob) (offsetof(PublicKeyBlob, PublicKey) + GET_UNALIGNED_VAL32(&(_pKeyBlob)->cbPublicKey)) @@ -260,20 +257,11 @@ const ULONG g_coreLibPublicKeyLen = ARRAY_SIZE(g_rbTheSilverlightPlatformKey); #define SN_THE_SILVERLIGHT_KEYTOKEN() ((PublicKeyBlob*)g_rbTheSilverlightKeyToken) - -// Free buffer allocated by routines below. -VOID StrongNameFreeBuffer(BYTE *pbMemory) // [in] address of memory to free -{ - if (pbMemory != (BYTE*)SN_MICROSOFT_KEY() && pbMemory != g_rbNeutralPublicKey) - delete [] pbMemory; -} - - // Create a strong name token from a public key blob. HRESULT StrongNameTokenFromPublicKey(BYTE *pbPublicKeyBlob, // [in] public key blob ULONG cbPublicKeyBlob, - BYTE **ppbStrongNameToken, // [out] strong name token - ULONG *pcbStrongNameToken) + BYTE(&tokenBuffer)[SN_SIZEOF_TOKEN] // [out] strong name token +) { HRESULT hr = S_OK; @@ -292,33 +280,27 @@ HRESULT StrongNameTokenFromPublicKey(BYTE *pbPublicKeyBlob, // [in] pu } // Allocate a buffer for the output token. - *ppbStrongNameToken = new (nothrow) BYTE[SN_SIZEOF_TOKEN]; - if (*ppbStrongNameToken == NULL) { - hr = E_OUTOFMEMORY; - goto Exit; - } - *pcbStrongNameToken = SN_SIZEOF_TOKEN; // We cache a couple of common cases. if (SN_IS_NEUTRAL_KEY(pbPublicKeyBlob)) { - memcpy_s(*ppbStrongNameToken, *pcbStrongNameToken, g_rbNeutralPublicKeyToken, SN_SIZEOF_TOKEN); + memcpy_s(tokenBuffer, SN_SIZEOF_TOKEN, g_rbNeutralPublicKeyToken, SN_SIZEOF_TOKEN); goto Exit; } if (cbPublicKeyBlob == SN_SIZEOF_MICROSOFT_KEY() && memcmp(pbPublicKeyBlob, SN_MICROSOFT_KEY(), cbPublicKeyBlob) == 0) { - memcpy_s(*ppbStrongNameToken, *pcbStrongNameToken, SN_MICROSOFT_KEYTOKEN(), SN_SIZEOF_TOKEN); + memcpy_s(tokenBuffer, SN_SIZEOF_TOKEN, SN_MICROSOFT_KEYTOKEN(), SN_SIZEOF_TOKEN); goto Exit; } if (SN_IS_THE_SILVERLIGHT_PLATFORM_KEY(pbPublicKeyBlob)) { - memcpy_s(*ppbStrongNameToken, *pcbStrongNameToken, SN_THE_SILVERLIGHT_PLATFORM_KEYTOKEN(), SN_SIZEOF_TOKEN); + memcpy_s(tokenBuffer, SN_SIZEOF_TOKEN, SN_THE_SILVERLIGHT_PLATFORM_KEYTOKEN(), SN_SIZEOF_TOKEN); goto Exit; } if (SN_IS_THE_SILVERLIGHT_KEY(pbPublicKeyBlob)) { - memcpy_s(*ppbStrongNameToken, *pcbStrongNameToken, SN_THE_SILVERLIGHT_KEYTOKEN(), SN_SIZEOF_TOKEN); + memcpy_s(tokenBuffer, SN_SIZEOF_TOKEN, SN_THE_SILVERLIGHT_KEYTOKEN(), SN_SIZEOF_TOKEN); goto Exit; } @@ -332,7 +314,7 @@ HRESULT StrongNameTokenFromPublicKey(BYTE *pbPublicKeyBlob, // [in] pu // low order bytes from a network byte order point of view). Reverse the // order of these bytes in the output buffer to get host byte order. for (i = 0; i < SN_SIZEOF_TOKEN; i++) - (*ppbStrongNameToken)[SN_SIZEOF_TOKEN - (i + 1)] = pHash[i + dwHashLenMinusTokenSize]; + (tokenBuffer)[SN_SIZEOF_TOKEN - (i + 1)] = pHash[i + dwHashLenMinusTokenSize]; goto Exit; diff --git a/src/coreclr/vm/assemblyspec.cpp b/src/coreclr/vm/assemblyspec.cpp index 416f0491365d7..8654fa3805a37 100644 --- a/src/coreclr/vm/assemblyspec.cpp +++ b/src/coreclr/vm/assemblyspec.cpp @@ -20,7 +20,6 @@ #include "assemblyspec.hpp" #include "eeconfig.h" #include "strongnameinternal.h" -#include "strongnameholders.h" #include "eventtrace.h" #include "assemblynative.hpp" @@ -331,16 +330,14 @@ void AssemblySpec::MatchPublicKeys(Assembly *pAssembly) else { // Ref has a token - StrongNameBufferHolder pbStrongNameToken; - DWORD cbStrongNameToken; + BYTE strongNameToken[SN_SIZEOF_TOKEN]; IfFailThrow(StrongNameTokenFromPublicKey((BYTE*)pbPublicKey, cbPublicKey, - &pbStrongNameToken, - &cbStrongNameToken)); + strongNameToken)); - if ((m_cbPublicKeyOrToken != cbStrongNameToken) || - memcmp(m_pbPublicKeyOrToken, pbStrongNameToken, cbStrongNameToken)) + if ((m_cbPublicKeyOrToken != SN_SIZEOF_TOKEN) || + memcmp(m_pbPublicKeyOrToken, strongNameToken, SN_SIZEOF_TOKEN)) { ThrowHR(FUSION_E_REF_DEF_MISMATCH); } @@ -576,15 +573,13 @@ HRESULT AssemblySpec::EmitToken( // If we've been asked to emit a public key token in the reference but we've // been given a public key then we need to generate the token now. if (m_cbPublicKeyOrToken && IsAfPublicKey(m_dwFlags)) { - StrongNameBufferHolder pbPublicKeyToken; - DWORD cbPublicKeyToken; + BYTE strongNameToken[SN_SIZEOF_TOKEN]; IfFailThrow(StrongNameTokenFromPublicKey(m_pbPublicKeyOrToken, m_cbPublicKeyOrToken, - &pbPublicKeyToken, - &cbPublicKeyToken)); + strongNameToken)); - hr = pEmit->DefineAssemblyRef(pbPublicKeyToken, - cbPublicKeyToken, + hr = pEmit->DefineAssemblyRef(strongNameToken, + SN_SIZEOF_TOKEN, ssName.GetUnicode(), &AMD, NULL, diff --git a/src/coreclr/vm/baseassemblyspec.cpp b/src/coreclr/vm/baseassemblyspec.cpp index 31d10243480f2..fe94765fc8e9c 100644 --- a/src/coreclr/vm/baseassemblyspec.cpp +++ b/src/coreclr/vm/baseassemblyspec.cpp @@ -13,7 +13,6 @@ #include "common.h" #include "strongnameinternal.h" -#include "strongnameholders.h" BOOL BaseAssemblySpec::IsCoreLib() { @@ -93,15 +92,13 @@ VOID BaseAssemblySpec::ConvertPublicKeyToToken() } CONTRACTL_END; - StrongNameBufferHolder pbPublicKeyToken; - DWORD cbPublicKeyToken; + BYTE strongNameToken[SN_SIZEOF_TOKEN]; IfFailThrow(StrongNameTokenFromPublicKey(m_pbPublicKeyOrToken, m_cbPublicKeyOrToken, - &pbPublicKeyToken, - &cbPublicKeyToken)); + strongNameToken)); - BYTE *temp = new BYTE [cbPublicKeyToken]; - memcpy(temp, pbPublicKeyToken, cbPublicKeyToken); + BYTE *temp = new BYTE [SN_SIZEOF_TOKEN]; + memcpy(temp, strongNameToken, SN_SIZEOF_TOKEN); if (m_ownedFlags & PUBLIC_KEY_OR_TOKEN_OWNED) delete [] m_pbPublicKeyOrToken; @@ -109,7 +106,7 @@ VOID BaseAssemblySpec::ConvertPublicKeyToToken() m_ownedFlags |= PUBLIC_KEY_OR_TOKEN_OWNED; m_pbPublicKeyOrToken = temp; - m_cbPublicKeyOrToken = cbPublicKeyToken; + m_cbPublicKeyOrToken = SN_SIZEOF_TOKEN; m_dwFlags &= ~afPublicKey; } diff --git a/src/coreclr/vm/coreassemblyspec.cpp b/src/coreclr/vm/coreassemblyspec.cpp index 2fc79fab37ab9..ce18afbad7eb3 100644 --- a/src/coreclr/vm/coreassemblyspec.cpp +++ b/src/coreclr/vm/coreassemblyspec.cpp @@ -19,7 +19,6 @@ #include "holder.h" #include "bundle.h" #include "strongnameinternal.h" -#include "strongnameholders.h" #include "../binder/inc/assemblyidentity.hpp" #include "../binder/inc/assembly.hpp" @@ -378,16 +377,14 @@ VOID BaseAssemblySpec::GetDisplayName(DWORD flags, SString &result) const } else { - DWORD cbToken = 0; - StrongNameBufferHolder pbToken; + BYTE strongNameToken[SN_SIZEOF_TOKEN]; // Try to get the strong name IfFailThrow(StrongNameTokenFromPublicKey(m_pbPublicKeyOrToken, m_cbPublicKeyOrToken, - &pbToken, - &cbToken)); + strongNameToken)); - assemblyIdentity.m_publicKeyOrTokenBLOB.Set(pbToken, cbToken); + assemblyIdentity.m_publicKeyOrTokenBLOB.Set(strongNameToken, SN_SIZEOF_TOKEN); } } else From 9df06b67e1cf596416c107f7e1c7bb479c6b1928 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Tue, 5 Dec 2023 11:10:08 -0800 Subject: [PATCH 06/10] Encapsulate the strong name token buffer into a struct to make it easier to use. --- src/coreclr/binder/utils.cpp | 7 ++-- src/coreclr/inc/strongnameinternal.h | 9 +++-- src/coreclr/md/compiler/importhelper.cpp | 36 +++++++++---------- src/coreclr/md/runtime/strongnameinternal.cpp | 18 +++++----- src/coreclr/vm/assemblyspec.cpp | 16 ++++----- src/coreclr/vm/baseassemblyspec.cpp | 10 +++--- src/coreclr/vm/coreassemblyspec.cpp | 6 ++-- 7 files changed, 50 insertions(+), 52 deletions(-) diff --git a/src/coreclr/binder/utils.cpp b/src/coreclr/binder/utils.cpp index a40608271f46f..f1b916ec9dc1a 100644 --- a/src/coreclr/binder/utils.cpp +++ b/src/coreclr/binder/utils.cpp @@ -54,15 +54,14 @@ namespace BINDER_SPACE const BYTE *pByteKey = publicKeyBLOB; DWORD dwKeyLen = publicKeyBLOB.GetSize(); - BYTE pByteToken[SN_SIZEOF_TOKEN]; + StrongNameToken token; IF_FAIL_GO(StrongNameTokenFromPublicKey( const_cast(pByteKey), dwKeyLen, - pByteToken)); + &token)); - _ASSERTE(pByteToken != NULL); - publicKeyTokenBLOB.Set(pByteToken, SN_SIZEOF_TOKEN); + publicKeyTokenBLOB.Set(token.m_token, StrongNameToken::SIZEOF_TOKEN); Exit: return hr; diff --git a/src/coreclr/inc/strongnameinternal.h b/src/coreclr/inc/strongnameinternal.h index a478592f561ca..8588664c7c9a1 100644 --- a/src/coreclr/inc/strongnameinternal.h +++ b/src/coreclr/inc/strongnameinternal.h @@ -18,12 +18,15 @@ typedef struct { BYTE PublicKey[1]; // variable length byte array containing the key value in format output by CryptoAPI } PublicKeyBlob; -// Number of bytes for a strong name token. -constexpr ULONG SN_SIZEOF_TOKEN = 8; +struct StrongNameToken +{ + static constexpr ULONG SIZEOF_TOKEN = 8; + BYTE m_token[SIZEOF_TOKEN]; +}; HRESULT StrongNameTokenFromPublicKey(BYTE* pbPublicKeyBlob, // [in] public key blob ULONG cbPublicKeyBlob, - BYTE(&tokenBuffer)[SN_SIZEOF_TOKEN] // [out] strong name token + StrongNameToken* token // [out] strong name token ); #endif // !_STRONGNAME_INTERNAL_H diff --git a/src/coreclr/md/compiler/importhelper.cpp b/src/coreclr/md/compiler/importhelper.cpp index 2c873c5a50723..d1b2ac55fdc6d 100644 --- a/src/coreclr/md/compiler/importhelper.cpp +++ b/src/coreclr/md/compiler/importhelper.cpp @@ -1313,12 +1313,10 @@ HRESULT ImportHelper::FindAssemblyRef( const void *pbTmp; // Temp blob. ULONG cbTmp; // Temp byte count. DWORD dwTmp; // Temp flags. - const BYTE tokenBuffer[SN_SIZEOF_TOKEN]; // Local buffer for token version of public key. const void *pbToken = NULL; // Token version of public key. ULONG cbToken = 0; // Count of bytes in token. #if !defined(FEATURE_METADATA_EMIT_IN_DEBUGGER) || defined(DACCESS_COMPILE) - const void *pbTmpToken; // Token version of public key. - ULONG cbTmpToken; // Count of bytes in token. + StrongNameToken token; // Local buffer for token version of public key. bool fMatch; // Did public key or tokens match? #endif // !FEATURE_METADATA_EMIT_IN_DEBUGGER || DACCESS_COMPILE @@ -1393,12 +1391,12 @@ HRESULT ImportHelper::FindAssemblyRef( #if defined(FEATURE_METADATA_EMIT_IN_DEBUGGER) && !defined(DACCESS_COMPILE) return E_FAIL; #else //!FEATURE_METADATA_EMIT_IN_DEBUGGER || DACCESS_COMPILE - const BYTE tmpTokenBuffer[SN_SIZEOF_TOKEN]; + StrongNameToken tmpToken; // Need to compress target public key to see if it matches. IfFailRet(StrongNameTokenFromPublicKey((BYTE*)pbTmp, cbTmp, - tmpTokenBuffer)); - fMatch = SN_SIZEOF_TOKEN == cbPublicKeyOrToken && !memcmp(pbTmpToken, pbPublicKeyOrToken, SN_SIZEOF_TOKEN); + &tmpToken)); + fMatch = StrongNameToken::SIZEOF_TOKEN == cbPublicKeyOrToken && !memcmp(&tmpToken, pbPublicKeyOrToken, StrongNameToken::SIZEOF_TOKEN); if (!fMatch) continue; #endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER || DACCESS_COMPILE @@ -1414,9 +1412,9 @@ HRESULT ImportHelper::FindAssemblyRef( #else //!FEATURE_METADATA_EMIT_IN_DEBUGGER || DACCESS_COMPILE IfFailRet(StrongNameTokenFromPublicKey((BYTE*)pbPublicKeyOrToken, cbPublicKeyOrToken, - tokenBuffer)); - pbToken = tokenBuffer; - cbToken = SN_SIZEOF_TOKEN; + &token)); + pbToken = &token; + cbToken = StrongNameToken::SIZEOF_TOKEN; #endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER || DACCESS_COMPILE } if (cbTmp != cbToken || memcmp(pbTmp, pbToken, cbToken)) @@ -3175,7 +3173,7 @@ ImportHelper::CreateAssemblyRefFromAssembly( LPCUTF8 szLocale; mdAssemblyRef tkAssemRef; HRESULT hr = S_OK; - BYTE pbToken[SN_SIZEOF_TOKEN]; + StrongNameToken token; ULONG i; // Set output to Nil. @@ -3194,7 +3192,7 @@ ImportHelper::CreateAssemblyRefFromAssembly( dwFlags &= ~afPublicKey; IfFailGo(StrongNameTokenFromPublicKey((BYTE*)pbPublicKey, cbPublicKey, - pbToken)); + &token)); } else _ASSERTE(!IsAfPublicKey(dwFlags)); @@ -3211,8 +3209,8 @@ ImportHelper::CreateAssemblyRefFromAssembly( continue; // See if the AssemblyRef already exists in the emit scope. - hr = FindAssemblyRef(pMiniMdEmit, szName, szLocale, pbToken, - SN_SIZEOF_TOKEN, usMajorVersion, usMinorVersion, + hr = FindAssemblyRef(pMiniMdEmit, szName, szLocale, &token, + StrongNameToken::SIZEOF_TOKEN, usMajorVersion, usMinorVersion, usBuildNumber, usRevisionNumber, dwFlags, &tkAssemRef); if (hr == CLDB_E_RECORD_NOTFOUND) @@ -3230,7 +3228,7 @@ ImportHelper::CreateAssemblyRefFromAssembly( pRecordEmit->SetFlags(dwFlags); IfFailGo(pMiniMdEmit->PutBlob(TBL_AssemblyRef, AssemblyRefRec::COL_PublicKeyOrToken, - pRecordEmit, pbToken, cbToken)); + pRecordEmit, &token, StrongNameToken::SIZEOF_TOKEN)); IfFailGo(pMiniMdEmit->PutString(TBL_AssemblyRef, AssemblyRefRec::COL_Name, pRecordEmit, szName)); IfFailGo(pMiniMdEmit->PutString(TBL_AssemblyRef, AssemblyRefRec::COL_Locale, @@ -3284,8 +3282,6 @@ HRESULT ImportHelper::CompareAssemblyRefToAssembly( // S_OK, S_FALSE or error ULONG cbPublicKey2; LPCUTF8 szName2; LPCUTF8 szLocale2; - const void *pbToken = NULL; - ULONG cbToken = 0; bool fMatch; // Get the AssemblyRef props. @@ -3326,15 +3322,15 @@ HRESULT ImportHelper::CompareAssemblyRefToAssembly( // S_OK, S_FALSE or error memcmp(pbPublicKeyOrToken1, pbPublicKey2, cbPublicKeyOrToken1))) return S_FALSE; - BYTE token[SN_SIZEOF_TOKEN]; + StrongNameToken token2; // Otherwise we need to compress the def public key into a token. IfFailRet(StrongNameTokenFromPublicKey((BYTE*)pbPublicKey2, cbPublicKey2, - token)); + &token2)); - fMatch = cbPublicKeyOrToken1 == cbToken && - !memcmp(pbPublicKeyOrToken1, pbToken, cbPublicKeyOrToken1); + fMatch = cbPublicKeyOrToken1 == StrongNameToken::SIZEOF_TOKEN && + !memcmp(pbPublicKeyOrToken1, &token2, cbPublicKeyOrToken1); if (!fMatch) return S_FALSE; diff --git a/src/coreclr/md/runtime/strongnameinternal.cpp b/src/coreclr/md/runtime/strongnameinternal.cpp index fc6625d5a7452..95d93818f1fbe 100644 --- a/src/coreclr/md/runtime/strongnameinternal.cpp +++ b/src/coreclr/md/runtime/strongnameinternal.cpp @@ -260,7 +260,7 @@ const ULONG g_coreLibPublicKeyLen = ARRAY_SIZE(g_rbTheSilverlightPlatformKey); // Create a strong name token from a public key blob. HRESULT StrongNameTokenFromPublicKey(BYTE *pbPublicKeyBlob, // [in] public key blob ULONG cbPublicKeyBlob, - BYTE(&tokenBuffer)[SN_SIZEOF_TOKEN] // [out] strong name token + StrongNameToken* pToken // [out] strong name token ) { HRESULT hr = S_OK; @@ -283,38 +283,38 @@ HRESULT StrongNameTokenFromPublicKey(BYTE *pbPublicKeyBlob, // [in] pu // We cache a couple of common cases. if (SN_IS_NEUTRAL_KEY(pbPublicKeyBlob)) { - memcpy_s(tokenBuffer, SN_SIZEOF_TOKEN, g_rbNeutralPublicKeyToken, SN_SIZEOF_TOKEN); + memcpy_s(pToken, StrongNameToken::SIZEOF_TOKEN, g_rbNeutralPublicKeyToken, StrongNameToken::SIZEOF_TOKEN); goto Exit; } if (cbPublicKeyBlob == SN_SIZEOF_MICROSOFT_KEY() && memcmp(pbPublicKeyBlob, SN_MICROSOFT_KEY(), cbPublicKeyBlob) == 0) { - memcpy_s(tokenBuffer, SN_SIZEOF_TOKEN, SN_MICROSOFT_KEYTOKEN(), SN_SIZEOF_TOKEN); + memcpy_s(pToken, StrongNameToken::SIZEOF_TOKEN, SN_MICROSOFT_KEYTOKEN(), StrongNameToken::SIZEOF_TOKEN); goto Exit; } if (SN_IS_THE_SILVERLIGHT_PLATFORM_KEY(pbPublicKeyBlob)) { - memcpy_s(tokenBuffer, SN_SIZEOF_TOKEN, SN_THE_SILVERLIGHT_PLATFORM_KEYTOKEN(), SN_SIZEOF_TOKEN); + memcpy_s(pToken, StrongNameToken::SIZEOF_TOKEN, SN_THE_SILVERLIGHT_PLATFORM_KEYTOKEN(), StrongNameToken::SIZEOF_TOKEN); goto Exit; } if (SN_IS_THE_SILVERLIGHT_KEY(pbPublicKeyBlob)) { - memcpy_s(tokenBuffer, SN_SIZEOF_TOKEN, SN_THE_SILVERLIGHT_KEYTOKEN(), SN_SIZEOF_TOKEN); + memcpy_s(pToken, StrongNameToken::SIZEOF_TOKEN, SN_THE_SILVERLIGHT_KEYTOKEN(), StrongNameToken::SIZEOF_TOKEN); goto Exit; } // Compute a hash over the public key. sha1.AddData(pbPublicKeyBlob, cbPublicKeyBlob); pHash = sha1.GetHash(); - static_assert(SHA1_HASH_SIZE >= SN_SIZEOF_TOKEN, "SN_SIZEOF_TOKEN must be smaller or equal to the SHA1_HASH_SIZE"); - dwHashLenMinusTokenSize = SHA1_HASH_SIZE - SN_SIZEOF_TOKEN; + static_assert(SHA1_HASH_SIZE >= StrongNameToken::SIZEOF_TOKEN, "StrongNameToken::SIZEOF_TOKEN must be smaller or equal to the SHA1_HASH_SIZE"); + dwHashLenMinusTokenSize = SHA1_HASH_SIZE - StrongNameToken::SIZEOF_TOKEN; // Take the last few bytes of the hash value for our token. (These are the // low order bytes from a network byte order point of view). Reverse the // order of these bytes in the output buffer to get host byte order. - for (i = 0; i < SN_SIZEOF_TOKEN; i++) - (tokenBuffer)[SN_SIZEOF_TOKEN - (i + 1)] = pHash[i + dwHashLenMinusTokenSize]; + for (i = 0; i < StrongNameToken::SIZEOF_TOKEN; i++) + pToken->m_token[StrongNameToken::SIZEOF_TOKEN - (i + 1)] = pHash[i + dwHashLenMinusTokenSize]; goto Exit; diff --git a/src/coreclr/vm/assemblyspec.cpp b/src/coreclr/vm/assemblyspec.cpp index 8654fa3805a37..6144f000a8e05 100644 --- a/src/coreclr/vm/assemblyspec.cpp +++ b/src/coreclr/vm/assemblyspec.cpp @@ -330,14 +330,14 @@ void AssemblySpec::MatchPublicKeys(Assembly *pAssembly) else { // Ref has a token - BYTE strongNameToken[SN_SIZEOF_TOKEN]; + StrongNameToken strongNameToken; IfFailThrow(StrongNameTokenFromPublicKey((BYTE*)pbPublicKey, cbPublicKey, - strongNameToken)); + &strongNameToken)); - if ((m_cbPublicKeyOrToken != SN_SIZEOF_TOKEN) || - memcmp(m_pbPublicKeyOrToken, strongNameToken, SN_SIZEOF_TOKEN)) + if ((m_cbPublicKeyOrToken != StrongNameToken::SIZEOF_TOKEN) || + memcmp(m_pbPublicKeyOrToken, &strongNameToken, StrongNameToken::SIZEOF_TOKEN)) { ThrowHR(FUSION_E_REF_DEF_MISMATCH); } @@ -573,13 +573,13 @@ HRESULT AssemblySpec::EmitToken( // If we've been asked to emit a public key token in the reference but we've // been given a public key then we need to generate the token now. if (m_cbPublicKeyOrToken && IsAfPublicKey(m_dwFlags)) { - BYTE strongNameToken[SN_SIZEOF_TOKEN]; + StrongNameToken strongNameToken; IfFailThrow(StrongNameTokenFromPublicKey(m_pbPublicKeyOrToken, m_cbPublicKeyOrToken, - strongNameToken)); + &strongNameToken)); - hr = pEmit->DefineAssemblyRef(strongNameToken, - SN_SIZEOF_TOKEN, + hr = pEmit->DefineAssemblyRef(&strongNameToken, + StrongNameToken::SIZEOF_TOKEN, ssName.GetUnicode(), &AMD, NULL, diff --git a/src/coreclr/vm/baseassemblyspec.cpp b/src/coreclr/vm/baseassemblyspec.cpp index fe94765fc8e9c..1e4a0856bcd37 100644 --- a/src/coreclr/vm/baseassemblyspec.cpp +++ b/src/coreclr/vm/baseassemblyspec.cpp @@ -92,13 +92,13 @@ VOID BaseAssemblySpec::ConvertPublicKeyToToken() } CONTRACTL_END; - BYTE strongNameToken[SN_SIZEOF_TOKEN]; + StrongNameToken strongNameToken; IfFailThrow(StrongNameTokenFromPublicKey(m_pbPublicKeyOrToken, m_cbPublicKeyOrToken, - strongNameToken)); + &strongNameToken)); - BYTE *temp = new BYTE [SN_SIZEOF_TOKEN]; - memcpy(temp, strongNameToken, SN_SIZEOF_TOKEN); + BYTE *temp = new BYTE [StrongNameToken::SIZEOF_TOKEN]; + memcpy(temp, &strongNameToken, StrongNameToken::SIZEOF_TOKEN); if (m_ownedFlags & PUBLIC_KEY_OR_TOKEN_OWNED) delete [] m_pbPublicKeyOrToken; @@ -106,7 +106,7 @@ VOID BaseAssemblySpec::ConvertPublicKeyToToken() m_ownedFlags |= PUBLIC_KEY_OR_TOKEN_OWNED; m_pbPublicKeyOrToken = temp; - m_cbPublicKeyOrToken = SN_SIZEOF_TOKEN; + m_cbPublicKeyOrToken = StrongNameToken::SIZEOF_TOKEN; m_dwFlags &= ~afPublicKey; } diff --git a/src/coreclr/vm/coreassemblyspec.cpp b/src/coreclr/vm/coreassemblyspec.cpp index ce18afbad7eb3..886df7e4afbe5 100644 --- a/src/coreclr/vm/coreassemblyspec.cpp +++ b/src/coreclr/vm/coreassemblyspec.cpp @@ -377,14 +377,14 @@ VOID BaseAssemblySpec::GetDisplayName(DWORD flags, SString &result) const } else { - BYTE strongNameToken[SN_SIZEOF_TOKEN]; + StrongNameToken strongNameToken; // Try to get the strong name IfFailThrow(StrongNameTokenFromPublicKey(m_pbPublicKeyOrToken, m_cbPublicKeyOrToken, - strongNameToken)); + &strongNameToken)); - assemblyIdentity.m_publicKeyOrTokenBLOB.Set(strongNameToken, SN_SIZEOF_TOKEN); + assemblyIdentity.m_publicKeyOrTokenBLOB.Set(strongNameToken.m_token, StrongNameToken::SIZEOF_TOKEN); } } else From 3a47da9a3484cd7517956712d2e73deaa13a01e3 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Tue, 5 Dec 2023 12:03:11 -0800 Subject: [PATCH 07/10] Refactor well-known token lookup to use StrongNameToken. Add all keys that Arcade includes to catch all assemblies we ship. --- src/coreclr/md/runtime/strongnameinternal.cpp | 177 ++++++++++-------- 1 file changed, 101 insertions(+), 76 deletions(-) diff --git a/src/coreclr/md/runtime/strongnameinternal.cpp b/src/coreclr/md/runtime/strongnameinternal.cpp index 95d93818f1fbe..862955d8f8fa8 100644 --- a/src/coreclr/md/runtime/strongnameinternal.cpp +++ b/src/coreclr/md/runtime/strongnameinternal.cpp @@ -12,14 +12,18 @@ namespace { - // The byte values of the ECMA pseudo public key and its token. - const BYTE g_rbNeutralPublicKey[] = { 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0 }; - const BYTE g_rbNeutralPublicKeyToken[] = { 0xb7, 0x7a, 0x5c, 0x56, 0x19, 0x34, 0xe0, 0x89 }; - // The byte values of the real public keys and their corresponding tokens // for assemblies we ship. // These blobs allow us to skip the token calculation for our assemblies. - static const BYTE g_rbMicrosoftKey[] = + // Each of these keys corresponds to the public key in a file in the Arcade SDK. + + // The byte values of the ECMA pseudo public key and its token. + // Arcade SDK StrongNameKeyId: ECMA + const BYTE NeutralPublicKey[] = { 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0 }; + const BYTE NeutralPublicKeyToken[] = { 0xb7, 0x7a, 0x5c, 0x56, 0x19, 0x34, 0xe0, 0x89 }; + + // Arcade SDK StrongNameKeyId: Microsoft + static const BYTE MicrosoftKey[] = { 0x00,0x24,0x00,0x00,0x04,0x80,0x00,0x00,0x94,0x00,0x00,0x00,0x06,0x02,0x00,0x00, 0x00,0x24,0x00,0x00,0x52,0x53,0x41,0x31,0x00,0x04,0x00,0x00,0x01,0x00,0x01,0x00, @@ -33,9 +37,10 @@ namespace 0x26,0x1c,0x8a,0x12,0x43,0x65,0x18,0x20,0x6d,0xc0,0x93,0x34,0x4d,0x5a,0xd2,0x93 }; - static const BYTE g_rbMicrosoftKeyToken[] = {0xb0,0x3f,0x5f,0x7f,0x11,0xd5,0x0a,0x3a}; + static const StrongNameToken MicrosoftKeyToken = {{0xb0,0x3f,0x5f,0x7f,0x11,0xd5,0x0a,0x3a}}; - static const BYTE g_rbTheSilverlightPlatformKey[] = + // Arcade SDK StrongNameKeyId: SilverlightPlatform + static const BYTE SilverlightPlatformKey[] = { 0x00,0x24,0x00,0x00,0x04,0x80,0x00,0x00,0x94,0x00,0x00,0x00,0x06,0x02,0x00,0x00, 0x00,0x24,0x00,0x00,0x52,0x53,0x41,0x31,0x00,0x04,0x00,0x00,0x01,0x00,0x01,0x00, @@ -49,9 +54,10 @@ namespace 0x00,0xae,0xc2,0x32,0xf6,0xc6,0xb1,0xc7,0x85,0xb4,0x30,0x5c,0x12,0x3b,0x37,0xab }; - static const BYTE g_rbTheSilverlightPlatformKeyToken[] = {0x7c,0xec,0x85,0xd7,0xbe,0xa7,0x79,0x8e}; + static const StrongNameToken SilverlightPlatformKeyToken = {{0x7c,0xec,0x85,0xd7,0xbe,0xa7,0x79,0x8e}}; - static const BYTE g_rbTheSilverlightKey[] = + // Arcade SDK StrongNameKeyId: MicrosoftShared + static const BYTE SilverlightKey[] = { 0x00,0x24,0x00,0x00,0x04,0x80,0x00,0x00,0x94,0x00,0x00,0x00,0x06,0x02,0x00,0x00, 0x00,0x24,0x00,0x00,0x52,0x53,0x41,0x31,0x00,0x04,0x00,0x00,0x01,0x00,0x01,0x00, @@ -65,7 +71,78 @@ namespace 0xf4,0x6b,0x2a,0x2b,0x12,0x47,0xad,0xc3,0x65,0x2b,0xf5,0xc3,0x08,0x05,0x5d,0xa9 }; - static const BYTE g_rbTheSilverlightKeyToken[] = {0x31,0xBF,0x38,0x56,0xAD,0x36,0x4E,0x35}; + static const StrongNameToken SilverlightKeyToken = {{0x31,0xBF,0x38,0x56,0xAD,0x36,0x4E,0x35}}; + + // Arcade SDK StrongNameKeyId: MicrosoftAspNetCore + static const BYTE AspNetCoreKey[] = + { + 0x00,0x24,0x00,0x00,0x04,0x80,0x00,0x00,0x94,0x00,0x00,0x00,0x06,0x02,0x00,0x00, + 0x00,0x24,0x00,0x00,0x52,0x53,0x41,0x31,0x00,0x04,0x00,0x00,0x01,0x00,0x01,0x00, + 0xF3,0x3A,0x29,0x04,0x4F,0xA9,0xD7,0x40,0xC9,0xB3,0x21,0x3A,0x93,0xE5,0x7C,0x84, + 0xB4,0x72,0xC8,0x4E,0x0B,0x8A,0x0E,0x1A,0xE4,0x8E,0x67,0xA9,0xF8,0xF6,0xDE,0x9D, + 0x5F,0x7F,0x3D,0x52,0xAC,0x23,0xE4,0x8A,0xC5,0x18,0x01,0xF1,0xDC,0x95,0x0A,0xBE, + 0x90,0x1D,0xA3,0x4D,0x2A,0x9E,0x3B,0xAA,0xDB,0x14,0x1A,0x17,0xC7,0x7E,0xF3,0xC5, + 0x65,0xDD,0x5E,0xE5,0x05,0x4B,0x91,0xCF,0x63,0xBB,0x3C,0x6A,0xB8,0x3F,0x72,0xAB, + 0x3A,0xAF,0xE9,0x3D,0x0F,0xC3,0xC2,0x34,0x8B,0x76,0x4F,0xAF,0xB0,0xB1,0xC0,0x73, + 0x3D,0xE5,0x14,0x59,0xAE,0xAB,0x46,0x58,0x03,0x84,0xBF,0x9D,0x74,0xC4,0xE2,0x81, + 0x64,0xB7,0xCD,0xE2,0x47,0xF8,0x91,0xBA,0x07,0x89,0x1C,0x9D,0x87,0x2A,0xD2,0xBB + }; + + static const StrongNameToken AspNetCoreKeyToken = + { + {0xad, 0xb9, 0x79, 0x38, 0x29, 0xdd, 0xae, 0x60} + }; + + // Arcade SDK StrongNameKeyId: Open + static const BYTE OpenKey[] = + { + 0x00,0x24,0x00,0x00,0x04,0x80,0x00,0x00,0x94,0x00,0x00,0x00,0x06,0x02,0x00,0x00, + 0x00,0x24,0x00,0x00,0x52,0x53,0x41,0x31,0x00,0x04,0x00,0x00,0x01,0x00,0x01,0x00, + 0x4B,0x86,0xC4,0xCB,0x78,0x54,0x9B,0x34,0xBA,0xB6,0x1A,0x3B,0x18,0x00,0xE2,0x3B, + 0xFE,0xB5,0xB3,0xEC,0x39,0x00,0x74,0x04,0x15,0x36,0xA7,0xE3,0xCB,0xD9,0x7F,0x5F, + 0x04,0xCF,0x0F,0x85,0x71,0x55,0xA8,0x92,0x8E,0xAA,0x29,0xEB,0xFD,0x11,0xCF,0xBB, + 0xAD,0x3B,0xA7,0x0E,0xFE,0xA7,0xBD,0xA3,0x22,0x6C,0x6A,0x8D,0x37,0x0A,0x4C,0xD3, + 0x03,0xF7,0x14,0x48,0x6B,0x6E,0xBC,0x22,0x59,0x85,0xA6,0x38,0x47,0x1E,0x6E,0xF5, + 0x71,0xCC,0x92,0xA4,0x61,0x3C,0x00,0xB8,0xFA,0x65,0xD6,0x1C,0xCE,0xE0,0xCB,0xE5, + 0xF3,0x63,0x30,0xC9,0xA0,0x1F,0x41,0x83,0x55,0x9F,0x1B,0xEF,0x24,0xCC,0x29,0x17, + 0xC6,0xD9,0x13,0xE3,0xA5,0x41,0x33,0x3A,0x1D,0x05,0xD9,0xBE,0xD2,0x2B,0x38,0xCB + }; + + static const StrongNameToken OpenKeyToken = + { + {0xcc, 0x7b, 0x13, 0xff, 0xcd, 0x2d, 0xdd, 0x51} + }; + + struct WellKnownKey + { + BYTE const* const PublicKey; + const ULONG PublicKeyLen; + StrongNameToken const* const Token; + }; + + static const WellKnownKey WellKnownKeys[] = + { + { MicrosoftKey, sizeof(MicrosoftKey), &MicrosoftKeyToken }, + { SilverlightPlatformKey, sizeof(SilverlightPlatformKey), &SilverlightPlatformKeyToken }, + { SilverlightKey, sizeof(SilverlightKey), &SilverlightKeyToken }, + { AspNetCoreKey, sizeof(AspNetCoreKey), &AspNetCoreKeyToken }, + { OpenKey, sizeof(OpenKey), &OpenKeyToken }, + }; + + bool GetTokenForWellKnownKey(BYTE* key, ULONG keyLength, StrongNameToken* token) + { + for (size_t i = 0; i < ARRAYSIZE(WellKnownKeys); i++) + { + if (keyLength == WellKnownKeys[i].PublicKeyLen && + memcmp(key, WellKnownKeys[i].PublicKey, keyLength) == 0) + { + *token = *WellKnownKeys[i].Token; + return true; + } + } + + return false; + } //--------------------------------------------------------------------------------------- // @@ -105,8 +182,8 @@ namespace } CONTRACTL_END; - return StrongNameSizeOfPublicKey(keyPublicKey) == sizeof(g_rbNeutralPublicKey) && - memcmp(reinterpret_cast(&keyPublicKey), g_rbNeutralPublicKey, sizeof(g_rbNeutralPublicKey)) == 0; + return StrongNameSizeOfPublicKey(keyPublicKey) == sizeof(NeutralPublicKey) && + memcmp(reinterpret_cast(&keyPublicKey), NeutralPublicKey, sizeof(NeutralPublicKey)) == 0; } //--------------------------------------------------------------------------------------- @@ -128,7 +205,7 @@ namespace CONTRACTL_END; // The key should be the same size as the ECMA key - if (cbKey != sizeof(g_rbNeutralPublicKey)) + if (cbKey != sizeof(NeutralPublicKey)) { return false; } @@ -225,37 +302,8 @@ namespace } } -BYTE const* const g_coreLibPublicKey = g_rbTheSilverlightPlatformKey; -const ULONG g_coreLibPublicKeyLen = ARRAY_SIZE(g_rbTheSilverlightPlatformKey); - -// Determine the size of a PublicKeyBlob structure given the size of the key -// portion. -#define SN_SIZEOF_KEY(_pKeyBlob) (offsetof(PublicKeyBlob, PublicKey) + GET_UNALIGNED_VAL32(&(_pKeyBlob)->cbPublicKey)) - - -#define SN_MICROSOFT_KEY() ((PublicKeyBlob*)g_rbMicrosoftKey) -#define SN_SIZEOF_MICROSOFT_KEY() sizeof(g_rbMicrosoftKey) - -#define SN_MICROSOFT_KEYTOKEN() ((PublicKeyBlob*)g_rbMicrosoftKeyToken) - -// Determine if the given public key blob is the neutral key. -#define SN_IS_NEUTRAL_KEY(_pk) (SN_SIZEOF_KEY((PublicKeyBlob*)(_pk)) == sizeof(g_rbNeutralPublicKey) && \ - memcmp((_pk), g_rbNeutralPublicKey, sizeof(g_rbNeutralPublicKey)) == 0) - -#define SN_IS_MICROSOFT_KEY(_pk) (SN_SIZEOF_KEY((PublicKeyBlob*)(_pk)) == sizeof(g_rbMicrosoftKey) && \ - memcmp((_pk), g_rbMicrosoftKey, sizeof(g_rbMicrosoftKey)) == 0) - - -// Silverlight platform key -#define SN_THE_SILVERLIGHT_PLATFORM_KEYTOKEN() ((PublicKeyBlob*)g_rbTheSilverlightPlatformKeyToken) -#define SN_IS_THE_SILVERLIGHT_PLATFORM_KEY(_pk) (SN_SIZEOF_KEY((PublicKeyBlob*)(_pk)) == sizeof(g_rbTheSilverlightPlatformKey) && \ - memcmp((_pk), g_rbTheSilverlightPlatformKey, sizeof(g_rbTheSilverlightPlatformKey)) == 0) - -// Silverlight key -#define SN_IS_THE_SILVERLIGHT_KEY(_pk) (SN_SIZEOF_KEY((PublicKeyBlob*)(_pk)) == sizeof(g_rbTheSilverlightKey) && \ - memcmp((_pk), g_rbTheSilverlightKey, sizeof(g_rbTheSilverlightKey)) == 0) - -#define SN_THE_SILVERLIGHT_KEYTOKEN() ((PublicKeyBlob*)g_rbTheSilverlightKeyToken) +BYTE const* const g_coreLibPublicKey = SilverlightPlatformKey; +const ULONG g_coreLibPublicKeyLen = ARRAY_SIZE(SilverlightPlatformKey); // Create a strong name token from a public key blob. HRESULT StrongNameTokenFromPublicKey(BYTE *pbPublicKeyBlob, // [in] public key blob @@ -263,10 +311,12 @@ HRESULT StrongNameTokenFromPublicKey(BYTE *pbPublicKeyBlob, // [in] pu StrongNameToken* pToken // [out] strong name token ) { +#ifdef DACCESS_COMPILE + DacNotImpl(); + return S_OK; +#endif HRESULT hr = S_OK; -#ifndef DACCESS_COMPILE - SHA1Hash sha1; BYTE *pHash = NULL; DWORD i; @@ -275,33 +325,15 @@ HRESULT StrongNameTokenFromPublicKey(BYTE *pbPublicKeyBlob, // [in] pu if (!StrongNameIsValidPublicKey(pbPublicKeyBlob, cbPublicKeyBlob)) { - hr = CORSEC_E_INVALID_PUBLICKEY; - goto Exit; + return CORSEC_E_INVALID_PUBLICKEY; } - // Allocate a buffer for the output token. - // We cache a couple of common cases. - if (SN_IS_NEUTRAL_KEY(pbPublicKeyBlob)) { - memcpy_s(pToken, StrongNameToken::SIZEOF_TOKEN, g_rbNeutralPublicKeyToken, StrongNameToken::SIZEOF_TOKEN); - goto Exit; - } - if (cbPublicKeyBlob == SN_SIZEOF_MICROSOFT_KEY() && - memcmp(pbPublicKeyBlob, SN_MICROSOFT_KEY(), cbPublicKeyBlob) == 0) { - memcpy_s(pToken, StrongNameToken::SIZEOF_TOKEN, SN_MICROSOFT_KEYTOKEN(), StrongNameToken::SIZEOF_TOKEN); - goto Exit; - } - - if (SN_IS_THE_SILVERLIGHT_PLATFORM_KEY(pbPublicKeyBlob)) + // This allows us to speed up assembly loading for assemblies we ship in the .NET SDK + // and member resolution from other assemblies into those assemblies. + if (GetTokenForWellKnownKey(pbPublicKeyBlob, cbPublicKeyBlob, pToken)) { - memcpy_s(pToken, StrongNameToken::SIZEOF_TOKEN, SN_THE_SILVERLIGHT_PLATFORM_KEYTOKEN(), StrongNameToken::SIZEOF_TOKEN); - goto Exit; - } - - if (SN_IS_THE_SILVERLIGHT_KEY(pbPublicKeyBlob)) - { - memcpy_s(pToken, StrongNameToken::SIZEOF_TOKEN, SN_THE_SILVERLIGHT_KEYTOKEN(), StrongNameToken::SIZEOF_TOKEN); - goto Exit; + return S_OK; } // Compute a hash over the public key. @@ -316,12 +348,5 @@ HRESULT StrongNameTokenFromPublicKey(BYTE *pbPublicKeyBlob, // [in] pu for (i = 0; i < StrongNameToken::SIZEOF_TOKEN; i++) pToken->m_token[StrongNameToken::SIZEOF_TOKEN - (i + 1)] = pHash[i + dwHashLenMinusTokenSize]; - goto Exit; - -Exit: -#else - DacNotImpl(); -#endif // #ifndef DACCESS_COMPILE - return hr; } From 406d8b9a9f00e43584c666db78978aedd18e8e22 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Tue, 5 Dec 2023 12:11:06 -0800 Subject: [PATCH 08/10] Add missing ECMA token --- src/coreclr/md/runtime/strongnameinternal.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/coreclr/md/runtime/strongnameinternal.cpp b/src/coreclr/md/runtime/strongnameinternal.cpp index 862955d8f8fa8..73c62b0aacd86 100644 --- a/src/coreclr/md/runtime/strongnameinternal.cpp +++ b/src/coreclr/md/runtime/strongnameinternal.cpp @@ -20,7 +20,7 @@ namespace // The byte values of the ECMA pseudo public key and its token. // Arcade SDK StrongNameKeyId: ECMA const BYTE NeutralPublicKey[] = { 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0 }; - const BYTE NeutralPublicKeyToken[] = { 0xb7, 0x7a, 0x5c, 0x56, 0x19, 0x34, 0xe0, 0x89 }; + const StrongNameToken NeutralPublicKeyToken = {{ 0xb7, 0x7a, 0x5c, 0x56, 0x19, 0x34, 0xe0, 0x89 }}; // Arcade SDK StrongNameKeyId: Microsoft static const BYTE MicrosoftKey[] = @@ -122,6 +122,7 @@ namespace static const WellKnownKey WellKnownKeys[] = { + { NeutralPublicKey, sizeof(NeutralPublicKey), &NeutralPublicKeyToken }, { MicrosoftKey, sizeof(MicrosoftKey), &MicrosoftKeyToken }, { SilverlightPlatformKey, sizeof(SilverlightPlatformKey), &SilverlightPlatformKeyToken }, { SilverlightKey, sizeof(SilverlightKey), &SilverlightKeyToken }, From c10a95fc3726433ab75e67e19ba084bf4f866da3 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Tue, 5 Dec 2023 12:12:21 -0800 Subject: [PATCH 09/10] Fix Array size macro --- src/coreclr/md/runtime/strongnameinternal.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/md/runtime/strongnameinternal.cpp b/src/coreclr/md/runtime/strongnameinternal.cpp index 73c62b0aacd86..9198875c99c46 100644 --- a/src/coreclr/md/runtime/strongnameinternal.cpp +++ b/src/coreclr/md/runtime/strongnameinternal.cpp @@ -132,7 +132,7 @@ namespace bool GetTokenForWellKnownKey(BYTE* key, ULONG keyLength, StrongNameToken* token) { - for (size_t i = 0; i < ARRAYSIZE(WellKnownKeys); i++) + for (size_t i = 0; i < ARRAY_SIZE(WellKnownKeys); i++) { if (keyLength == WellKnownKeys[i].PublicKeyLen && memcmp(key, WellKnownKeys[i].PublicKey, keyLength) == 0) From b8d4291635783d863770d7959e004659c4b0f178 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Wed, 6 Dec 2023 11:02:58 -0800 Subject: [PATCH 10/10] Fix incorrect sizeof and remove unused define --- src/coreclr/vm/baseassemblyspec.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/coreclr/vm/baseassemblyspec.cpp b/src/coreclr/vm/baseassemblyspec.cpp index 1e4a0856bcd37..469535aa7f4db 100644 --- a/src/coreclr/vm/baseassemblyspec.cpp +++ b/src/coreclr/vm/baseassemblyspec.cpp @@ -40,9 +40,6 @@ BOOL BaseAssemblySpec::IsCoreLib() ( (iNameLen == CoreLibNameLen) || (m_pAssemblyName[CoreLibNameLen] == ',') ) ) ) ); } -#define CORELIB_PUBLICKEY g_rbTheSilverlightPlatformKey - - // A satellite assembly for CoreLib is named "System.Private.CoreLib.resources" or // System.Private.CoreLib.debug.resources.dll and uses the same public key as CoreLib. // It does not necessarily have the same version, and the Culture will @@ -70,7 +67,7 @@ BOOL BaseAssemblySpec::IsCoreLibSatellite() const size_t iNameLen = strlen(m_pAssemblyName); // we allow name to be of the form System.Private.CoreLib.resources.dll only - BOOL r = ( (m_cbPublicKeyOrToken == sizeof(g_coreLibPublicKey)) && + BOOL r = ( (m_cbPublicKeyOrToken == g_coreLibPublicKeyLen) && (iNameLen >= CoreLibSatelliteNameLen) && (!SString::_strnicmp(m_pAssemblyName, g_psBaseLibrarySatelliteAssemblyName, CoreLibSatelliteNameLen)) && ( (iNameLen == CoreLibSatelliteNameLen) || (m_pAssemblyName[CoreLibSatelliteNameLen] == ',') ) );