Cách mã hóa byte bằng TPM (Mô-đun nền tảng đáng tin cậy)


110

Làm cách nào để mã hóa byte bằng mô-đun TPM của máy?

CryptProtectData

Windows cung cấp một API (tương đối) đơn giản để mã hóa một blob bằng cách sử dụng CryptProtectDataAPI, mà chúng ta có thể bọc một hàm dễ sử dụng:

public Byte[] ProtectBytes(Byte[] plaintext)
{
   //...
}

Các chi tiết ProtectBytesít quan trọng hơn ý tưởng mà bạn có thể sử dụng nó khá dễ dàng:

  • đây là các byte tôi muốn được mã hóa bởi một khóa bí mật được giữ trong System
  • trả lại cho tôi blob được mã hóa

Blob trả về là một cấu trúc tài liệu không có giấy tờ , chứa mọi thứ cần thiết để giải mã và trả về dữ liệu gốc (thuật toán băm, thuật toán mật mã, muối, chữ ký HMAC, v.v.).

Để hoàn thiện, đây là cách triển khai mã giả mẫu ProtectBytessử dụng Crypt APIbyte để bảo vệ:

public Byte[] ProtectBytes(Byte[] plaintext)
{
   //Setup our n-byte plaintext blob
   DATA_BLOB dataIn;
   dataIn.cbData = plaintext.Length;
   dataIn.pbData = Addr(plaintext[0]);

   DATA_BLOB dataOut;

   //dataOut = EncryptedFormOf(dataIn)
   BOOL bRes = CryptProtectData(
         dataIn,
         null,     //data description (optional PWideChar)
         null,     //optional entropy (PDATA_BLOB)
         null,     //reserved
         null,     //prompt struct
         CRYPTPROTECT_UI_FORBIDDEN || CRYPTPROTECT_LOCAL_MACHINE,
         ref dataOut);
   if (!bRes) then
   {
      DWORD le = GetLastError();
      throw new Win32Error(le, "Error calling CryptProtectData");
   }

   //Copy ciphertext from dataOut blob into an actual array
   bytes[] result;
   SetLength(result, dataOut.cbData);
   CopyMemory(dataOut.pbData, Addr(result[0]), dataOut.cbData);

   //When you have finished using the DATA_BLOB structure, free its pbData member by calling the LocalFree function
   LocalFree(HANDLE(dataOut.pbData)); //LocalFree takes a handle, not a pointer. But that's what the SDK says.
}

Làm thế nào để làm điều tương tự với TPM?

Đoạn mã trên chỉ hữu ích để mã hóa dữ liệu cho máy cục bộ. Dữ liệu được mã hóa bằng cách sử dụng Systemtài khoản làm trình tạo khóa (các chi tiết, tuy thú vị, nhưng không quan trọng ). Kết quả cuối cùng là tôi có thể mã hóa dữ liệu (ví dụ: khóa chính mã hóa ổ cứng) mà chỉ máy cục bộ mới có thể giải mã được.

Bây giờ là lúc để tiến thêm một bước nữa. Tôi muốn mã hóa một số dữ liệu (ví dụ: khóa chính mã hóa ổ cứng) mà chỉ có thể được giải mã bởi TPM cục bộ. Nói cách khác, tôi muốn thay thế Môi trường thực thi tin cậy Qualcomm ( TEE ) trong sơ đồ khối bên dưới cho Android, bằng TPM trong Windows:

nhập mô tả hình ảnh ở đây

Lưu ý : Tôi nhận thấy rằng TPM không thực hiện việc ký dữ liệu (hoặc nếu có, nó không đảm bảo rằng việc ký cùng một dữ liệu sẽ cho cùng một đầu ra nhị phân mỗi lần). Đó là lý do tại sao tôi sẵn sàng thay thế "ký RSA" bằng "mã hóa một đốm màu 256-bit bằng khóa liên kết phần cứng" .

Vậy mã ở đâu?

Vấn đề là lập trình TPM hoàn toàn không có tài liệu trên MSDN . Không có sẵn API để thực hiện bất kỳ hoạt động nào. Thay vào đó, bạn phải tìm cho mình một bản sao của Ngăn xếp phần mềm của Nhóm Máy tính Tin cậy (hay còn gọi là TSS) , hãy tìm ra các lệnh cần gửi đến TPM, với trọng tải, theo thứ tự nào và gọi hàm Tbsip_Submit_Command của Window để gửi lệnh trực tiếp:

TBS_RESULT Tbsip_Submit_Command(
  _In_     TBS_HCONTEXT hContext,
  _In_     TBS_COMMAND_LOCALITY Locality,
  _In_     TBS_COMMAND_PRIORITY Priority,
  _In_     const PCBYTE *pabCommand,
  _In_     UINT32 cbCommand,
  _Out_    PBYTE *pabResult,
  _Inout_  UINT32 *pcbOutput
);

Windows không có API cấp cao hơn để thực hiện các hành động.

Nó tương đương với đạo đức của việc cố gắng tạo một tệp văn bản bằng cách đưa ra các lệnh SATA I / O vào ổ cứng của bạn .

Tại sao không chỉ sử dụng Quần tây

Trusted Computing Group (TCG) đã xác định API của riêng họ: TCB Software Stack (TSS) . Một số người đã tạo ra một bản triển khai API này và được gọi là TrouSerS . Một chàng trai sau đó đã chuyển dự án đó sang Windows .

Vấn đề với mã đó là nó không thể di động vào thế giới Windows. Ví dụ, bạn không thể sử dụng nó từ Delphi, bạn không thể sử dụng nó từ C #. Nó yêu cầu:

  • OpenSSL
  • pThread

Tôi chỉ muốn để mã hóa thứ gì đó bằng TPM của mình.

Trên CryptProtectData không yêu cầu gì khác ngoài những gì trong cơ thể hàm.

Mã tương đương để mã hóa dữ liệu bằng TPM là gì? Như những người khác đã lưu ý, bạn có thể phải tham khảo ba hướng dẫn sử dụng TPM và tự xây dựng các đốm màu . Nó có thể liên quan đến TPM_seallệnh. Mặc dù tôi nghĩ tôi không muốn niêm phong dữ liệu, nhưng tôi nghĩ tôi muốn ràng buộc nó:

Ràng buộc - mã hóa dữ liệu bằng khóa liên kết TPM, một khóa RSA duy nhất có nguồn gốc từ khóa lưu trữ. Niêm phong - mã hóa dữ liệu theo cách tương tự như ràng buộc, nhưng ngoài ra còn chỉ định trạng thái mà TPM phải ở để dữ liệu được giải mã (chưa được niêm phong)

Tôi cố gắng đọc ba tập cần thiết để tìm 20 dòng mã tôi cần:

Nhưng tôi không có biết mình đang đọc gì. Nếu có bất kỳ loại hướng dẫn hoặc ví dụ nào, tôi có thể có một shot. Nhưng tôi hoàn toàn lạc lối.

Vì vậy, chúng tôi yêu cầu Stackoverflow

Theo cách tương tự, tôi có thể cung cấp:

Byte[] ProtectBytes_Crypt(Byte[] plaintext)
{
   //...
   CryptProtectData(...); 
   //...
}

ai đó có thể cung cấp tương đương tương ứng:

Byte[] ProtectBytes_TPM(Byte[] plaintext)
{
   //...
   Tbsip_Submit_Command(...);
   Tbsip_Submit_Command(...);
   Tbsip_Submit_Command(...);
   //...snip...
   Tbsip_Submit_Command(...);
   //...
}

điều đó cũng làm điều tương tự, ngoại trừ một chìa khóa bị khóa System LSA, bị khóa trong TPM?

Bắt đầu nghiên cứu

Tôi không biết chính xác ràng buộc nghĩa là gì. Nhưng nhìn vào TPM Main - Phần 3 Lệnh - Đặc tả Phiên bản 1.2, có đề cập đến ràng buộc :

10,3 TPM_UnBind

TPM_UnBind lấy khối dữ liệu là kết quả của lệnh Tspi_Data_Bind và giải mã nó để xuất cho Người dùng. Người gọi phải cho phép sử dụng khóa sẽ giải mã khối đến. TPM_UnBind hoạt động trên cơ sở từng khối và không có khái niệm về bất kỳ mối quan hệ nào giữa khối này với khối khác.

Điều khó hiểu không có Tspi_Data_Bindlệnh.

Nỗ lực Nghiên cứu

Thật là kinh hoàng khi không ai thèm ghi lại TPM hoặc hoạt động của nó. Cứ như thể họ đã dành tất cả thời gian để nghĩ ra thứ hay ho này để chơi cùng, nhưng không muốn đối mặt với bước đau đớn là biến nó có thể sử dụng được cho một thứ gì đó.

Bắt đầu với cuốn sách miễn phí (hiện tại) Hướng dẫn Thực hành về TPM 2.0: Sử dụng Mô-đun Nền tảng Tin cậy trong Kỷ nguyên Bảo mật Mới :

Chương 3 - Hướng dẫn nhanh về TPM 2.0

TPM có quyền truy cập vào khóa cá nhân tự tạo, vì vậy nó có thể mã hóa các khóa bằng khóa công khai và sau đó lưu trữ khối kết quả trên đĩa cứng. Bằng cách này, TPM có thể giữ cho số lượng khóa hầu như không giới hạn để sử dụng nhưng không lãng phí bộ nhớ trong có giá trị. Các phím được lưu trên đĩa cứng có thể bị xóa, nhưng chúng cũng có thể được sao lưu, điều này đối với các nhà thiết kế dường như là một sự đánh đổi có thể chấp nhận được.

Làm cách nào để mã hóa khóa bằng khóa công khai của TPM?

Chương 4 - Các ứng dụng hiện có sử dụng TPM

Các ứng dụng nên sử dụng TPM nhưng không

Trong vài năm qua, số lượng các ứng dụng dựa trên web đã tăng lên. Trong số đó có sao lưu và lưu trữ dựa trên web. Một số lượng lớn các công ty hiện cung cấp các dịch vụ như vậy, nhưng theo chúng tôi được biết, không có khách hàng nào của các dịch vụ này cho phép người dùng khóa chìa khóa của dịch vụ sao lưu vào TPM. Nếu điều này được thực hiện, chắc chắn sẽ rất tuyệt nếu bản thân khóa TPM được sao lưu bằng cách sao chép nó trên nhiều máy. Đây dường như là một cơ hội cho các nhà phát triển.

Làm thế nào để một nhà phát triển khóa một chìa khóa cho TPM?

Chương 9 - Heirarchies

TRƯỜNG HỢP SỬ DỤNG: LƯU TRỮ MẬT KHẨU ĐĂNG NHẬP

Một tệp mật khẩu điển hình lưu trữ các mật khẩu băm nhỏ. Việc xác minh bao gồm việc ướp muối và băm một mật khẩu đã cung cấp và so sánh nó với giá trị được lưu trữ. Bởi vì tính toán không bao gồm bí mật, nó có thể bị tấn công ngoại tuyến vào tệp mật khẩu.

Trường hợp sử dụng này sử dụng khóa HMAC do TPM tạo. Tệp mật khẩu lưu trữ một HMAC của mật khẩu muối. Xác minh bao gồm ướp muối và HMAC mật khẩu được cung cấp và so sánh nó với giá trị được lưu trữ. Vì kẻ tấn công ngoại tuyến không có khóa HMAC, kẻ tấn công không thể thực hiện một cuộc tấn công bằng cách thực hiện phép tính.

Điều này có thể hoạt động. Nếu TPM có khóa HMAC bí mật và chỉ TPM của tôi biết khóa HMAC, thì tôi có thể thay thế "Ký (hay còn gọi là mã hóa TPM bằng khóa riêng)" bằng "HMAC". Nhưng sau đó ở dòng tiếp theo, anh ấy đảo ngược hoàn toàn bản thân:

TPM2_Create, chỉ định một khóa HMAC

Đó không phải là bí mật TPM nếu tôi phải chỉ định khóa HMAC. Thực tế là khóa HMAC không phải là bí mật có ý nghĩa khi bạn nhận ra đây là chương về các tiện ích mật mã mà TPM cung cấp. Thay vì bạn phải tự viết SHA2, AES, HMAC hoặc RSA, bạn có thể sử dụng lại những gì TPM đã có sẵn.

Chương 10 - Phím

Là một thiết bị bảo mật, khả năng ứng dụng sử dụng khóa trong khi vẫn giữ chúng an toàn trong thiết bị phần cứng là điểm mạnh nhất của TPM. TPM có thể tạo và nhập các khóa được tạo bên ngoài. Nó hỗ trợ cả phím bất đối xứng và đối xứng.

Thông minh! Bạn làm nó như thế nào!?

Trình tạo khóa

Có thể cho rằng, sức mạnh lớn nhất của TPM là khả năng tạo khóa mật mã và bảo vệ bí mật của nó trong ranh giới phần cứng. Bộ tạo khóa dựa trên bộ tạo số ngẫu nhiên của TPM và không dựa vào các nguồn ngẫu nhiên bên ngoài. Do đó, nó loại bỏ các điểm yếu dựa trên phần mềm phần mềm yếu với nguồn entropy không đủ.

Liệu TPM có khả năng tạo ra các khóa mật mã và bảo vệ bí mật của nó trong vòng một ranh giới phần cứng? Là như vậy, làm thế nào?

Chương 12 - Thanh ghi cấu hình nền tảng

PCR để cho phép

SỬ DỤNG TRƯỜNG HỢP: ĐÓNG KHÓA KÍCH THÍCH ĐĨA CỨNG VÀO TIỂU BIỂU TÌNH

Các ứng dụng mã hóa toàn đĩa an toàn hơn nhiều nếu TPM bảo vệ khóa mã hóa hơn là nếu nó được lưu trữ trên cùng một đĩa, chỉ được bảo vệ bằng mật khẩu. Đầu tiên, phần cứng TPM có bảo vệ chống búa (xem Chương 8 để biết mô tả chi tiết về bảo vệ chống tấn công từ điển TPM), khiến một cuộc tấn công brute-force vào mật khẩu là không thực tế. Một khóa chỉ được bảo vệ bằng phần mềm sẽ dễ bị tấn công hơn nhiều so với mật khẩu yếu. Thứ hai, khóa phần mềm được lưu trữ trên đĩa dễ bị đánh cắp hơn nhiều. Lấy đĩa (hoặc một bản sao lưu của đĩa) và bạn sẽ có được chìa khóa. Khi TPM giữ chìa khóa, toàn bộ nền tảng, hoặc ít nhất là đĩa và bo mạch chủ, phải bị đánh cắp.

Việc niêm phong cho phép khóa được bảo vệ không chỉ bằng mật khẩu mà còn bằng chính sách. Một chính sách điển hình sẽ khóa khóa đối với các giá trị PCR (trạng thái phần mềm) hiện tại tại thời điểm niêm phong. Điều này giả định rằng trạng thái lúc khởi động đầu tiên không bị xâm phạm. Bất kỳ phần mềm độc hại được cài đặt sẵn nào có mặt ở lần khởi động đầu tiên sẽ được đo lường trong PCR và do đó khóa sẽ được niêm phong ở trạng thái phần mềm bị xâm phạm. Một doanh nghiệp kém tin tưởng hơn có thể có hình ảnh đĩa tiêu chuẩn và con dấu đối với PCR đại diện cho hình ảnh đó. Các giá trị PCR này sẽ được tính toán trước trên một nền tảng được cho là đáng tin cậy hơn. Một doanh nghiệp thậm chí còn phức tạp hơn sẽ sử dụng TPM2_PolicyAuthorize và cung cấp một số vé cho phép một tập hợp các giá trị PCR đáng tin cậy. Xem Chương 14 để biết mô tả chi tiết về ủy quyền chính sách và ứng dụng của nó để giải quyết vấn đề PCRbrittleness.

Mặc dù mật khẩu cũng có thể bảo vệ khóa, nhưng có một lợi ích bảo mật ngay cả khi không có mật khẩu khóa TPM. Kẻ tấn công có thể khởi động nền tảng mà không cần cung cấp mật khẩu TPMkey nhưng không thể đăng nhập nếu không có tên người dùng và mật khẩu hệ điều hành. OSsecurity bảo vệ dữ liệu. Kẻ tấn công có thể khởi động một hệ điều hành thay thế, chẳng hạn như từ đĩa DVD hoặc USB trực tiếp thay vì từ ổ cứng, để vượt qua bảo mật đăng nhập hệ điều hành. Tuy nhiên, cấu hình khởi động và phần mềm khác nhau này sẽ thay đổi giá trị PCR. Vì các PCR mới này không khớp với các giá trị được niêm phong, TPM sẽ không phát hành khóa giải mã và không thể giải mã ổ cứng.

Thông minh! Đây chính xác là trường hợp sử dụng mà tôi muốn. Đây cũng là trường hợp sử dụng mà Microsoft sử dụng TPM. Tôi phải làm nó như thế nào!?

Vì vậy, tôi đọc toàn bộ cuốn sách đó, và nó không cung cấp gì hữu ích. Khá ấn tượng vì nó có 375 trang. Bạn tự hỏi cuốn sách chứa đựng những gì - và nhìn lại nó, tôi không biết.

Vì vậy, chúng tôi từ bỏ hướng dẫn cuối cùng để lập trình TPM và thay vào đó chuyển sang một số tài liệu từ Microsoft:

Từ Bộ công cụ nhà cung cấp tiền điện tử nền tảng TPM của Microsoft . Nó đề cập chính xác những gì tôi muốn làm:

Khóa xác nhận hoặc EK

EK được thiết kế để cung cấp một mã nhận dạng mật mã đáng tin cậy cho nền tảng. Một doanh nghiệp có thể duy trì cơ sở dữ liệu về các Khóa xác nhận thuộc về TPM của tất cả các PC trong doanh nghiệp của họ hoặc bộ điều khiển kết cấu trung tâm dữ liệu có thể có cơ sở dữ liệu về TPM trong tất cả các cánh. Trên Windows, bạn có thể sử dụng nhà cung cấp NCrypt được mô tả trong phần “Nhà cung cấp tiền điện tử nền tảng trong Windows 8” để đọc phần công khai của EK.

Ở đâu đó bên trong TPM là một khóa riêng RSA. Chìa khóa đó được khóa trong đó - không bao giờ bị thế giới bên ngoài nhìn thấy. Tôi muốn TPM ký một cái gì đó bằng khóa riêng của nó (tức là mã hóa nó bằng khóa riêng của nó).

Vì vậy, tôi muốn hoạt động cơ bản nhất có thể tồn tại:

nhập mô tả hình ảnh ở đây

Mã hóa thứ gì đó bằng khóa riêng của bạn. Tôi thậm chí chưa (chưa) yêu cầu những thứ phức tạp hơn:

  • "niêm phong" nó dựa trên trạng thái PCR
  • tạo khóa và lưu trữ nó trong memroy dễ bay hơi hoặc không bay hơi
  • tạo một khóa đối xứng và cố gắng tải nó vào TPM

Tôi đang yêu cầu hoạt động cơ bản nhất mà một TPM có thể thực hiện. Tại sao không thể nhận được bất kỳ thông tin về cách làm điều đó?

Tôi có thể lấy dữ liệu ngẫu nhiên

Tôi cho rằng tôi đã rất kinh ngạc khi nói rằng ký RSA là điều cơ bản nhất mà TPM có thể làm. Các nhất điều cơ bản TPM có thể được yêu cầu phải làm là cho tôi byte ngẫu nhiên. Điều đó tôi đã tìm ra cách làm:

public Byte[] GetRandomBytesTPM(int desiredBytes)
{
   //The maximum random number size is limited to 4,096 bytes per call
   Byte[] result = new Byte[desiredBytes];

   BCRYPT_ALG_HANDLE hAlgorithm;

   BCryptOpenAlgorithmProvider(
         out hAlgorithm,
         BCRYPT_RNG_ALGORITHM, //AlgorithmID: "RNG"
         MS_PLATFORM_CRYPTO_PROVIDER, //Implementation: "Microsoft Platform Crypto Provider" i.e. the TPM
         0 //Flags
   );
   try
   {                
      BCryptGenRandom(hAlgorithm, @result[0], desiredBytes, 0);
   }
   finally
   {
      BCryptCloseAlgorithmProvider(hAlgorithm);
   }

   return result;
}

The Fancy Thing

Tôi nhận thấy số lượng người sử dụng TPM rất thấp. Đó là lý do tại sao không ai trên Stackoverflow có câu trả lời. Vì vậy, tôi không thể thực sự quá tham lam trong việc tìm ra giải pháp cho vấn đề chung của mình. Nhưng điều tôi thực sự muốn làm là "niêm phong" một số dữ liệu:

nhập mô tả hình ảnh ở đây

  • trình bày TPM một số dữ liệu (ví dụ: 32 byte vật liệu chính)
  • có TPM mã hóa dữ liệu, trả về một số cấu trúc khối mờ
  • sau đó yêu cầu TPM giải mã đốm màu
  • việc giải mã sẽ chỉ hoạt động nếu các thanh ghi PCR của TPM giống như khi chúng được mã hóa.

Nói cách khác:

Byte[] ProtectBytes_TPM(Byte[] plaintext, Boolean sealToPcr)
{
   //...
}

Byte[] UnprotectBytes_TPM(Byte[] protectedBlob)
{
   //...
}

Cryptography Next Gen (Cng, hay còn gọi là BCrypt) hỗ trợ TPM

API mật mã ban đầu trong Windows được gọi là API Crypto.

Bắt đầu từ Windows Vista, API Crypto đã được thay thế bằng Cryptography API: Next Generation (tên gọi nội bộ là BestCrypt , viết tắt là BCrypt , đừng nhầm lẫn với thuật toán băm mật khẩu ).

Windows đi kèm với hai nhà cung cấp BCrypt :

  • Microsoft Primitive Provider ( MS_PRIMITIVE_PROVIDER) mặc định : Triển khai phần mềm mặc định của tất cả các phần mềm nguyên thủy (băm, mã hóa đối xứng, chữ ký số, v.v.)
  • Nhà cung cấp tiền điện tử nền tảng Microsoft ( MS_PLATFORM_CRYPTO_PROVIDER): Nhà cung cấp cung cấp quyền truy cập TPM

Nhà cung cấp tiền điện tử nền tảng không được ghi lại trên MSDN, nhưng có tài liệu từ trang web Nghiên cứu của Microsoft năm 2012:

Bộ công cụ nhà cung cấp tiền điện tử nền tảng TPM

Bộ công cụ và nhà cung cấp tiền điện tử nền tảng TPM chứa mã mẫu, tiện ích và tài liệu để sử dụng chức năng liên quan đến TPM trong Windows 8. Các hệ thống con được mô tả bao gồm nhà cung cấp tiền điện tử nền tảng Crypto-Next-Gen (CNG) được TPM hậu thuẫn và cách nhà cung cấp dịch vụ chứng thực có thể sử dụng các tính năng mới của Windows. Cả hai hệ thống dựa trên TPM1.2 và TPM2.0 đều được hỗ trợ.

Có vẻ như ý định của Microsoft là giới thiệu chức năng tiền điện tử TPM với Nhà cung cấp tiền điện tử nền tảng Microsoft của Cryptography NG API .

Mã hóa khóa công khai bằng Microsoft BCrypt

Cho rằng:

một con đường phía trước có thể là tìm ra cách thực hiện ký kỹ thuật số bằng cách sử dụng Microsoft Cryptography Next Gen API .

Bước tiếp theo của tôi sẽ là tìm ra mã để thực hiện mã hóa trong BCrypt, với khóa công khai RSA, sử dụng trình cung cấp tiêu chuẩn ( MS_PRIMITIVE_PROVIDER). Ví dụ:

  • modulus: 0xDC 67 FA F4 9E F2 72 1D 45 2C B4 80 79 06 A0 94 27 50 8209 DD 67 CE 57 B8 6C 4A 4F 40 9F D2 D1 69 FB 995D 85 0C 07 A1 F9 47 1B 56 16 6E F6 7F B9 CF 2A 58 36 37 99 29 AA 4F A8 12 E8 4F C7 82 2B 9D 72 2A 9C DE 6F C2 EE 12 6D CF F0 F2 B8 C4 DD 7C 5C 1A C8 17 51 A9 AC DF 08 22 04 9D 2B D7 F9 4B 09 DE 9A EB 5C 51 1A D8 F8 F9 56 9E F8 FB 37 9B 3F D3 74 65 24 0D FF 34 75 57 A4 F5 BF 55
  • publicExponent: 65537

Với mã đó đang hoạt động, tôi có thể chuyển sang sử dụng Nhà cung cấp TPM ( MS_PLATFORM_CRYPTO_PROVIDER).

22/2/2016: Và với việc Apple bắt buộc phải giúp giải mã dữ liệu người dùng, ngày càng có nhiều quan tâm đến việc làm thế nào để TPM thực hiện nhiệm vụ đơn giản nhất mà nó được phát minh ra - mã hóa thứ gì đó.

Nó gần tương đương với việc mọi người sở hữu một chiếc ô tô, nhưng không ai biết cách khởi động một chiếc ô tô. Nó có thể làm những điều thực sự hữu ích và thú vị, nếu chúng ta có thể vượt qua Bước 1 .

Đọc thêm


Đối với ràng buộc (mã hóa), không có chức năng rõ ràng nào khả dụng và nó cũng không cần thiết. Bạn chỉ cần tạo một khóa liên kết trong TPM và sử dụng phần công khai của nó để mã hóa khóa mã hóa đối xứng với chức năng mã hóa rsa của hệ thống ("RSA / ECB / OAEPWithSHA1AndMGF1Padding") và lưu nó theo đúng cấu trúc ("TcTssConstants.TSS_ENCDATA_BIND"). Để hủy liên kết (giải mã) sek, bạn chỉ cần sử dụng chức năng hủy liên kết TPM và sử dụng sek trong bất kỳ chức năng mã hóa đối xứng nào bạn thích. Tôi có một cơ sở mã khá cũ cho rằng tôi đã làm một số thời gian trước đây, có lẽ nó giúp: goo.gl/jV1Ouw
evildead

Từ wikipedia, Ràng buộc - mã hóa dữ liệu bằng khóa liên kết TPM, một khóa RSA duy nhất xuất phát từ khóa lưu trữ. en.wikipedia.org/wiki/Trusted_Platform_Module Âm thanh như cặp này các lệnh (TSpi_Data_Bind / TPM_UnBind) nên là đủ cho nhu cầu của bạn ...
Alex Mazzariol

1
Tôi không nghĩ rằng bạn phải sử dụng TPM trực tiếp. Nó được hỗ trợ thông qua các API CNG / NCryptXXX tiêu chuẩn và "Nhà cung cấp tiền điện tử nền tảng Microsoft" (dành cho các nền tảng hệ điều hành Windows gần đây và nếu phần cứng ổn và được kích hoạt tất nhiên). Có thể bạn có thể xem "Bộ công cụ nhà cung cấp tiền điện tử nền tảng TPM tại đây: research.microsoft.com/en-us/downloads/… cũng kiểm tra điều này: tiw2013.cse.psu.edu/slides/…
Simon Mourier

CryptProtectData không nhất thiết phải sử dụng TPM. Mặt khác, nếu bạn có thể có được một tay cầm CNG hoặc CSP hợp lệ cho TPM, bạn có thể sử dụng nó trong các chức năng tiền điện tử.
Michael Chourdakis

1
@ b3nj1 Không, tôi không có; không ai có thể trả lời câu hỏi.
Ian Boyd

Câu trả lời:


7

Lót

Tất cả những gì tiếp theo là về TPM 1.2. Hãy nhớ rằng Microsoft yêu cầu TPM 2.0 cho tất cả các phiên bản Windows trong tương lai. Thế hệ 2.0 về cơ bản khác với thế hệ 1.2

Không có giải pháp một dòng vì các nguyên tắc thiết kế TPM. Hãy coi TPM như một bộ vi điều khiển với tài nguyên hạn chế. Mục tiêu thiết kế chính của nó là rẻ nhưng vẫn an toàn. Vì vậy, TPM đã bị gạt tất cả các logic không cần thiết cho một hoạt động an toàn. Vì vậy, một TPM chỉ hoạt động khi bạn có ít nhất một số phần mềm ít nhiều chất lượng , đưa ra nhiều lệnh theo đúng thứ tự. Và những chuỗi lệnh đó có thể rất phức tạp. Đó là lý do tại sao TCG chỉ định TSS với một API được xác định rõ. Nếu bạn muốn theo cách Java, thậm chí còn có một API Java cấp cao . Tôi không biết về một dự án tương tự cho C # / .net

Phát triển

Trong trường hợp của bạn, tôi khuyên bạn nên xem phần mềm TPM của IBM.

Trong gói này, bạn sẽ tìm thấy 3 thành phần rất hữu ích:

  • một phần mềm giả lập TPM
  • một lib tpm nhẹ
  • một số tiện ích dòng lệnh cơ bản

Bạn không nhất thiết phải có phần mềm giả lập TPM, bạn cũng có thể kết nối với TPM HW của máy. Tuy nhiên, bạn có thể chặn các lệnh đã phát và xem các phản hồi, do đó tìm hiểu cách chúng được lắp ráp và cách chúng tương ứng với đặc tả lệnh.

Cấp độ cao

Điều kiện tiên quyết:

  1. TPM được kích hoạt
  2. Trình điều khiển TPM được tải
  3. bạn đã có quyền sở hữu TPM

Để bịt kín một đốm màu, bạn cần làm như sau:

  1. tạo một chìa khóa
  2. cất giữ key-blob ở đâu đó
  3. đảm bảo rằng khóa được tải trong TPM
  4. niêm phong đốm màu

Để hủy niêm phong, bạn cần:

  1. lấy key-blob
  2. nạp chìa khóa vào TPM
  3. mở ra các đốm màu kín

Bạn có thể lưu trữ key-blob trong cấu trúc dữ liệu mà bạn sử dụng để lưu trữ các byte được bảo vệ.

Hầu hết các lệnh TPM bạn cần là những lệnh được ủy quyền. Do đó, bạn cần thiết lập các phiên ủy quyền khi cần thiết. AFAIR đó chủ yếu là các phiên OSAP.

Các lệnh TPM

Hiện tại tôi không thể chạy phiên bản gỡ lỗi nên không thể cung cấp cho bạn trình tự chính xác. Vì vậy, hãy coi đây là một danh sách lệnh không có thứ tự mà bạn sẽ phải sử dụng:

  • TPM_OSAP
  • TPM_CreateWrapKey
  • TPM_LoadKey2
  • TPM_Seal

Nếu bạn cũng muốn đọc các giá trị PCR hiện tại:

  • TPM_PCRRead

Microsoft có thư viện được quản lý C # .NET của họ để sử dụng TPM . Họ cũng có một trình giả lập TPM , mà thư viện được quản lý có thể kết nối như một giải pháp thay thế gỡ lỗi nếu không có TPM thực. Họ cũng có Bộ công cụ dành cho nhà cung cấp nền tảng TPM , chứa tài liệu và mã mẫu để sử dụng TPM. Bây giờ giá như ai đó có thể tìm ra cách sử dụng TPM để mã hóa byte.
Ian Boyd

Hai liên kết đầu tiên của bạn chỉ là TPM 2.0. Nếu bạn muốn sử dụng những thứ này, tôi e rằng tôi không giúp được gì.
Scolytus

4

Khóa tin cậy và được mã hóa

Khóa tin cậy và khóa được mã hóa là hai loại khóa mới được thêm vào dịch vụ vòng khóa hạt nhân hiện có. Cả hai kiểu mới này đều là các khóa đối xứng có độ dài thay đổi và trong cả hai trường hợp, tất cả các khóa đều được tạo trong nhân và không gian người dùng chỉ nhìn thấy, lưu trữ và tải các đốm màu được mã hóa. Khóa tin cậy yêu cầu sự sẵn có của chip Mô-đun nền tảng đáng tin cậy (TPM) để bảo mật cao hơn, trong khi Chìa khóa được mã hóa có thể được sử dụng trên bất kỳ hệ thống nào. Tất cả các đốm màu cấp độ người dùng, được hiển thị và tải trong hex ascii để thuận tiện và được xác minh tính toàn vẹn.

Khóa tin cậy sử dụng TPM để tạo và niêm phong khóa. Các khóa được niêm phong dưới khóa RSA 2048 bit trong TPM và được niêm phong tùy chọn đối với các giá trị PCR (đo tính toàn vẹn) được chỉ định và chỉ được TPM mở niêm phong, nếu PCR và xác minh tính toàn vẹn đốm màu khớp nhau. Khóa tin cậy được tải có thể được cập nhật bằng các giá trị PCR mới (trong tương lai), vì vậy các khóa dễ dàng được di chuyển sang các giá trị pcr mới, chẳng hạn như khi cập nhật hạt nhân và initramfs. Cùng một khóa có thể có nhiều đốm màu được lưu dưới các giá trị PCR khác nhau, do đó dễ dàng hỗ trợ nhiều khởi động.

Theo mặc định, các khóa đáng tin cậy được niêm phong trong SRK, có giá trị ủy quyền mặc định (20 số không). Điều này có thể được thiết lập lúc takeownership với tiện ích của quần: tpm_takeownership -u -z.

Usage:
    keyctl add trusted name "new keylen [options]" ring
    keyctl add trusted name "load hex_blob [pcrlock=pcrnum]" ring
    keyctl update key "update [options]"
    keyctl print keyid

    options:
    keyhandle= ascii hex value of sealing key default 0x40000000 (SRK)
    keyauth=   ascii hex auth for sealing key default 0x00...i
        (40 ascii zeros)
    blobauth=  ascii hex auth for sealed data default 0x00...
        (40 ascii zeros)
    blobauth=  ascii hex auth for sealed data default 0x00...
        (40 ascii zeros)
    pcrinfo=   ascii hex of PCR_INFO or PCR_INFO_LONG (no default)
    pcrlock=   pcr number to be extended to "lock" blob
    migratable= 0|1 indicating permission to reseal to new PCR values,
                default 1 (resealing allowed)

keyctl printtrả về bản sao ascii hex của khóa niêm phong, ở định dạng TPM_STORED_DATA tiêu chuẩn. Độ dài khóa cho các khóa mới luôn tính bằng byte. Khóa tin cậy có thể là 32 - 128 byte (256 - 1024 bit), giới hạn trên là vừa với độ bền khóa SRK (RSA) 2048 bit, với tất cả cấu trúc / đệm cần thiết.

Các khóa được mã hóa không phụ thuộc vào TPM và nhanh hơn, vì chúng sử dụng AES để mã hóa / giải mã. Các khóa mới được tạo từ các số ngẫu nhiên do nhân tạo ra và được mã hóa / giải mã bằng khóa 'chính' được chỉ định. Khóa 'chính' có thể là loại khóa tin cậy hoặc khóa người dùng. Nhược điểm chính của các khóa được mã hóa là nếu chúng không được root trong một khóa đáng tin cậy, chúng chỉ an toàn như khóa người dùng mã hóa chúng. Do đó, khóa người dùng chính phải được tải theo cách an toàn nhất có thể, tốt nhất là ngay khi khởi động.

Phần được giải mã của các khóa được mã hóa có thể chứa một khóa đối xứng đơn giản hoặc một cấu trúc phức tạp hơn. Định dạng của cấu trúc phức tạp hơn là dành riêng cho ứng dụng, được xác định bằng 'định dạng'.

Usage:
    keyctl add encrypted name "new [format] key-type:master-key-name keylen"
        ring
    keyctl add encrypted name "load hex_blob" ring
    keyctl update keyid "update key-type:master-key-name"

format:= 'default | ecryptfs'
key-type:= 'trusted' | 'user'

Ví dụ về cách sử dụng khóa đáng tin cậy và được mã hóa

Tạo và lưu khóa tin cậy có tên "kmk" có độ dài 32 byte:

$ keyctl add trusted kmk "new 32" @u
440502848

$ keyctl show
Session Keyring
       -3 --alswrv    500   500  keyring: _ses
 97833714 --alswrv    500    -1   \_ keyring: _uid.500
440502848 --alswrv    500   500       \_ trusted: kmk

$ keyctl print 440502848
0101000000000000000001005d01b7e3f4a6be5709930f3b70a743cbb42e0cc95e18e915
3f60da455bbf1144ad12e4f92b452f966929f6105fd29ca28e4d4d5a031d068478bacb0b
27351119f822911b0a11ba3d3498ba6a32e50dac7f32894dd890eb9ad578e4e292c83722
a52e56a097e6a68b3f56f7a52ece0cdccba1eb62cad7d817f6dc58898b3ac15f36026fec
d568bd4a706cb60bb37be6d8f1240661199d640b66fb0fe3b079f97f450b9ef9c22c6d5d
dd379f0facd1cd020281dfa3c70ba21a3fa6fc2471dc6d13ecf8298b946f65345faa5ef0
f1f8fff03ad0acb083725535636addb08d73dedb9832da198081e5deae84bfaf0409c22b
e4a8aea2b607ec96931e6f4d4fe563ba

$ keyctl pipe 440502848 > kmk.blob

Tải khóa tin cậy từ blob đã lưu:

$ keyctl add trusted kmk "load `cat kmk.blob`" @u
268728824

$ keyctl print 268728824
0101000000000000000001005d01b7e3f4a6be5709930f3b70a743cbb42e0cc95e18e915
3f60da455bbf1144ad12e4f92b452f966929f6105fd29ca28e4d4d5a031d068478bacb0b
27351119f822911b0a11ba3d3498ba6a32e50dac7f32894dd890eb9ad578e4e292c83722
a52e56a097e6a68b3f56f7a52ece0cdccba1eb62cad7d817f6dc58898b3ac15f36026fec
d568bd4a706cb60bb37be6d8f1240661199d640b66fb0fe3b079f97f450b9ef9c22c6d5d
dd379f0facd1cd020281dfa3c70ba21a3fa6fc2471dc6d13ecf8298b946f65345faa5ef0
f1f8fff03ad0acb083725535636addb08d73dedb9832da198081e5deae84bfaf0409c22b
e4a8aea2b607ec96931e6f4d4fe563ba

Gửi lại khóa tin cậy dưới các giá trị pcr mới:

$ keyctl update 268728824 "update pcrinfo=`cat pcr.blob`"
$ keyctl print 268728824
010100000000002c0002800093c35a09b70fff26e7a98ae786c641e678ec6ffb6b46d805
77c8a6377aed9d3219c6dfec4b23ffe3000001005d37d472ac8a44023fbb3d18583a4f73
d3a076c0858f6f1dcaa39ea0f119911ff03f5406df4f7f27f41da8d7194f45c9f4e00f2e
df449f266253aa3f52e55c53de147773e00f0f9aca86c64d94c95382265968c354c5eab4
9638c5ae99c89de1e0997242edfb0b501744e11ff9762dfd951cffd93227cc513384e7e6
e782c29435c7ec2edafaa2f4c1fe6e7a781b59549ff5296371b42133777dcc5b8b971610
94bc67ede19e43ddb9dc2baacad374a36feaf0314d700af0a65c164b7082401740e489c9
7ef6a24defe4846104209bf0c3eced7fa1a672ed5b125fc9d8cd88b476a658a4434644ef
df8ae9a178e9f83ba9f08d10fa47e4226b98b0702f06b3b8

Người tiêu dùng ban đầu của các khóa đáng tin cậy là EVM, tại thời điểm khởi động, khóa này cần một khóa đối xứng chất lượng cao để HMAC bảo vệ siêu dữ liệu tệp. Việc sử dụng khóa đáng tin cậy cung cấp đảm bảo chắc chắn rằng khóa EVM không bị xâm phạm bởi sự cố cấp người dùng và khi được niêm phong với các giá trị PCR khởi động cụ thể, sẽ bảo vệ khỏi các cuộc tấn công khởi động và ngoại tuyến. Tạo và lưu khóa mã hóa "evm" bằng khóa tin cậy "kmk" ở trên:

tùy chọn 1: bỏ qua 'định dạng'

$ keyctl add encrypted evm "new trusted:kmk 32" @u
159771175

tùy chọn 2: xác định rõ ràng 'định dạng' là 'mặc định'

$ keyctl add encrypted evm "new default trusted:kmk 32" @u
159771175

$ keyctl print 159771175
default trusted:kmk 32 2375725ad57798846a9bbd240de8906f006e66c03af53b1b3
82dbbc55be2a44616e4959430436dc4f2a7a9659aa60bb4652aeb2120f149ed197c564e0
24717c64 5972dcb82ab2dde83376d82b2e3c09ffc

$ keyctl pipe 159771175 > evm.blob

Tải khóa được mã hóa "evm" từ blob đã lưu:

$ keyctl add encrypted evm "load `cat evm.blob`" @u
831684262

$ keyctl print 831684262
default trusted:kmk 32 2375725ad57798846a9bbd240de8906f006e66c03af53b1b3
82dbbc55be2a44616e4959430436dc4f2a7a9659aa60bb4652aeb2120f149ed197c564e0
24717c64 5972dcb82ab2dde83376d82b2e3c09ffc

Các mục đích sử dụng khác cho các khóa được mã hóa và đáng tin cậy, chẳng hạn như mã hóa đĩa và tệp được dự đoán. Đặc biệt, định dạng mới 'ecryptfs' đã được xác định để sử dụng các khóa mã hóa để gắn kết hệ thống tệp eCryptfs. Bạn có thể tìm thêm chi tiết về cách sử dụng trong tệp 'Documentation / security / key-ecryptfs.txt'.


Bạn có biết khi nào hai loại khóa mới này được thêm vào không? Ý tôi là ở phiên bản nào. Tôi hiện đang sử dụng 1,2 (gói công ty) và gói đó không hỗ trợ những gói này. Có thể trong 1.5+?
Acapulco

1
Nguồn của bài đăng này là gì? Sự kết thúc đề cập đến một tài liệuDocumentation/security/keys-ecryptfs.tx
goodguys_activate

Đây dường như là tất cả các lệnh gọi đến một chương trình dòng lệnh. Tôi không thấy mã nào về cách sử dụng TPM.
Ian Boyd

3

Làm cách nào để mã hóa byte bằng mô-đun TPM của máy?

Phụ thuộc vào ý định và hoàn cảnh của bạn:

  • Bạn có loại TPM nào (1 gia đình hoặc 2 gia đình)?
  • TPM ở trạng thái nào? Nó đã được sở hữu? Nó đã được cấp phép chưa?
  • Ngôn ngữ lập trình của bạn là gì?
  • Bạn muốn mã hóa hay ký tên? (điều đó mơ hồ so với phần còn lại của câu hỏi)
  • Dữ liệu bạn muốn mã hóa lớn đến mức nào?
  • Bạn muốn sử dụng khóa đối xứng hay khóa bất đối xứng?
  • Bạn muốn sử dụng một khóa đã tồn tại trên TPM hay bạn muốn nó tạo khóa trước?
  • Bằng cách "mã hóa" có lẽ bạn có nghĩa là "bọc một khóa"?
  • Bạn có muốn khóa dữ liệu đã mã hóa trong cấu hình hệ thống để chỉ có thể giải mã khi hệ thống trở lại cấu hình cũ không?
  • Bạn có muốn yêu cầu ủy quyền để giải mã không?
  • Có lẽ bạn không cần mã hóa mà nên lưu trữ dữ liệu trong TPM?
  • Nếu bạn đang lưu trữ dữ liệu trong TPM, bạn có muốn yêu cầu ủy quyền hoặc hệ thống ở một cấu hình cụ thể để truy xuất không?

Mỗi trường hợp sử dụng này (và nhiều trường hợp khác) - hoặc kết hợp của chúng - trình bày một đường dẫn triển khai khác nhau. Hãy nghĩ về TPM như một con dao của Quân đội Thụy Sĩ trong các thiết bị mật mã: bạn không thể làm được gì nhiều với nó, nhưng sự dễ sử dụng sẽ mang lại tính linh hoạt đó. Câu hỏi liên tục nảy sinh giữa mã hóa, ký và khóa với cấu hình hệ thống, nhưng phần chính của câu trả lời này sẽ xem xét lệnh Seal để đáp ứng hầu hết các nhu cầu được mô tả trong câu hỏi.

Bây giờ là lúc để tiến thêm một bước nữa. Tôi muốn mã hóa một số dữ liệu (ví dụ: khóa chính mã hóa ổ cứng) mà chỉ có thể được giải mã bởi TPM cục bộ.

Đây là lệnh Bind dùng cho (được thay thế bởi lệnh Create cho TPM 2). Bạn tải một khóa có nguồn gốc từ khóa có giới hạn TPM và mã hóa bằng khóa đó (hoặc trực tiếp bằng khóa liên kết phần cứng). Bằng cách này, dữ liệu chỉ có thể được giải mã với quyền truy cập vào cùng một TPM.

Nói cách khác, tôi muốn thay thế Môi trường thực thi tin cậy Qualcomm (TEE) trong sơ đồ khối bên dưới cho Android, bằng TPM trong Windows:

Không chắc liệu việc lặp lại toàn bộ quá trình này có phải là một ý tưởng hay hay không. Đối với một, không cần sử dụng thao tác ký ở bất kỳ đâu trong quy trình. Có vẻ như vào thời điểm Android 5 đang được phát triển, API Keystore bị giới hạn trong các hoạt động ký và xác minh. Dự đoán tốt nhất của tôi là nhóm mã hóa đĩa đã cố gắng hết sức để làm việc với những gì họ có và phát minh ra một thuật toán theo đó một trong các khóa trung gian được bắt nguồn từ thao tác , sử dụng khóa TEE được lưu trữ, do đó liên kết toàn bộ quá trình với một phần cứng- khóa ràng buộc chỉ có sẵn trên nền tảng - vì ký tên là cách duy nhất để làm điều đó vào thời điểm đó. Tuy nhiên, không cần phải hạn chế bản thân theo những cách như vậy nếu có quyền truy cập vào TPM, nó cung cấp cho bạn nhiều khả năng hơn bạn biết là bạn cần!

Tôi nhận thấy rằng TPM không thực hiện việc ký dữ liệu

Điều này là sai, cả hai phiên bản TPM đều hỗ trợ ký.

(hoặc nếu có, nó không đảm bảo rằng việc ký cùng một dữ liệu sẽ cho cùng một đầu ra nhị phân mọi lúc)

Điều này không có ý nghĩa. Việc ký cùng một dữ liệu với cùng một khóa sẽ tạo ra cùng một chữ ký. Bạn có thể nhầm lẫn thao tác ký với thao tác trích dẫn, thao tác này sẽ lẫn lộn với nhau.

Đó là lý do tại sao tôi sẵn sàng thay thế "ký RSA" bằng "mã hóa một đốm màu 256-bit bằng khóa liên kết phần cứng".

Đây thực sự nên là tùy chọn ưu tiên, mặc dù cả hai đều có thể thực hiện được với TPM. Xem ở trên.

Vấn đề là lập trình TPM hoàn toàn không có tài liệu trên MSDN. Không có sẵn API để thực hiện bất kỳ hoạt động nào.

Thật không may là không có nhiều tài liệu. Win API bị giới hạn ở một vài hàm TBS bị loại bỏ một cấp khỏi trình điều khiển.

Thay vào đó, bạn phải tìm cho mình một bản sao của Ngăn xếp phần mềm của Nhóm Máy tính Tin cậy (hay còn gọi là TSS), hãy tìm ra các lệnh cần gửi đến TPM, với trọng tải, theo thứ tự nào và gọi hàm Tbsip_Submit_Command của Window để gửi lệnh trực tiếp:

Trên thực tế, không, nếu bạn có TSS, bạn sẽ không phải sử dụng Tbsip_submit_Command(). Đó là toàn bộ điểm của việc có TSS - các chi tiết cấp thấp đã được trừu tượng hóa.

Windows không có API cấp cao hơn để thực hiện các hành động.

Vẫn đúng với TPM 1, nhưng đối với TPM 2 thì có TSS.MSR .

Nó tương đương với đạo đức của việc cố gắng tạo một tệp văn bản bằng cách đưa ra các lệnh SATA I / O vào ổ cứng của bạn.

Chính xác.

Tại sao không chỉ sử dụng Quần tây ... Vấn đề với mã đó là nó không thể di động vào thế giới Windows. Ví dụ, bạn không thể sử dụng nó từ Delphi, bạn không thể sử dụng nó từ C #. Nó yêu cầu: OpenSSL, pThread

Không rõ rằng đây là một thử thách không thể vượt qua. Việc truy cập TrouSerS thông qua một tương tác nên được ưu tiên hơn là viết lại tất cả mã cấu trúc dữ liệu. Ngoài ra, đã có doTSStại thời điểm viết câu hỏi.

Mã tương đương để mã hóa dữ liệu bằng TPM là gì? Nó có thể liên quan đến lệnh TPM_seal. Mặc dù tôi nghĩ tôi không muốn niêm phong dữ liệu, nhưng tôi nghĩ tôi muốn ràng buộc nó:

Câu hỏi có một trích dẫn mô tả sự khác biệt giữa hai lệnh, vì vậy không nên có nhiều sự nhầm lẫn. Việc niêm phong tương tự như ràng buộc, với một ràng buộc bổ sung là trạng thái hệ thống phải giống nhau để dữ liệu không được niêm phong.

Theo cách tương tự, tôi có thể cung cấp:

Byte[] ProtectBytes_Crypt(Byte[] plaintext)
{
   //...
   CryptProtectData(...); 
   //...
}

ai đó có thể cung cấp tương đương tương ứng:

Byte[] ProtectBytes_TPM(Byte[] plaintext)
{
   //...
   Tbsip_Submit_Command(...);
   Tbsip_Submit_Command(...);
   Tbsip_Submit_Command(...);
   //...snip...
   Tbsip_Submit_Command(...);
   //...
}

điều đó làm tương tự, ngoại trừ một khóa bị khóa trong Hệ thống LSA, bị khóa trong TPM?

Đầu tiên, cần phải chỉ ra rằng có hai phiên bản chính của TPM, chúng hoàn toàn không tương thích với nhau. Vì vậy, hầu như không có mã nào bạn đã viết cho TPM 1 sẽ hoạt động cho TPM 2. API TBS là mã chung duy nhất giữa hai mã này và công bằng với Microsoft, đây có thể là một trong những lý do tại sao API đó không bao giờ phát triển. Phần chính của câu trả lời sẽ trình bày mã cho TPM 1 vì hai lý do:

  • Câu hỏi được tải với các khái niệm cụ thể về TPM 1, vì vậy những người sử dụng TPM 1 có nhiều khả năng truy cập vào đây để tìm kiếm chúng
  • Có một Microsoft triển khai TSS cho TPM 2.

Thứ hai, hãy làm cho câu hỏi cụ thể hơn. Tôi đang diễn giải lại nó như sau:

How do I write code in C#, using only the TBS API, to interface with
an already owned and provisioned TPM to, without user interaction,
encrypt no more than 128 bytes of arbitrary data with an asymmetric
key already resident in the TPM and bound to it, but not protected
with a password, so that in order to decrypt the data the system may
need to be in the same state it was in at encryption time based on an
easily configurable variable?

Lệnh Seal phù hợp nhất cho việc này, vì nó thực hiện chức năng tương tự như lệnh Bind khi kích thước lựa chọn PCR được đặt thành 0, nhưng lựa chọn PCR có thể dễ dàng thay đổi để bao gồm bất kỳ PCR nào bạn muốn. Nó khiến người ta thắc mắc tại sao lệnh Bind lại được đưa vào thông số kỹ thuật, và như đã lưu ý, nó đã bị loại bỏ trong thông số kỹ thuật TPM 2 và cả hai được kết hợp trong một lệnh Tạo.

Đây là mã C # để sử dụng lệnh TPM 1.2 Seal để mã hóa dữ liệu chỉ với các chức năng TBS (lưu ý: mã này chưa được kiểm tra và không có khả năng hoạt động nếu không gỡ lỗi) :

[DllImport ("tbs.dll")]
unsafe static extern UInt32 Tbsi_Context_Create (UInt32 * version, IntPtr * hContext);

[DllImport ("tbs.dll")]
unsafe static extern UInt32 Tbsip_Context_Close (IntPtr hContext);

[DllImport ("tbs.dll")]
unsafe static extern UInt32 Tbsip_Submit_Command (
    IntPtr hContext, UInt32 Locality, 
    UInt32 Priority, 
    byte * pCommandBuf, 
    UInt32 CommandBufLen, 
    byte * pResultBuf, 
    UInt32 * pResultBufLen);

byte[] ProtectBytes_TPM (byte[] plaintext) {

    void AddUInt32Reversed (byte[] a, System.UInt32 o, ref int i) {
        byte[] bytes = System.BitConverter.GetBytes (o);
        Array.Reverse (bytes);
        Array.Copy (bytes, 0, a, i, bytes.Length);
        i += bytes.Length;
    }
    void AddUInt16Reversed (byte[] a, System.UInt16 o, ref int i) {
        byte[] bytes = System.BitConverter.GetBytes (o);
        Array.Reverse (bytes);
        Array.Copy (bytes, 0, a, i, bytes.Length);
        i += bytes.Length;
    }
    void AddBool (byte[] a, byte b, ref int i) {
        a[i] = b;
        i += 1;
    }
    void AddBlob (byte[] a, byte[] b, ref int i) {
        Array.Copy (b, 0, a, i, b.Length);
        i += b.Length;
    }
    byte[] Xor (byte[] text, byte[] key) {
        byte[] xor = new byte[text.Length];
        for (int i = 0; i < text.Length; i++) {
            xor[i] = (byte) (text[i] ^ key[i % key.Length]);
        }
        return xor;
    }

    int offset;

    Random rnd = new Random ();

    IntPtr hContext = IntPtr.Zero;
    unsafe {
        UInt32 version = 1;
        IntPtr handle = hContext;
        UInt32 result = Tbsi_Context_Create ( & version, & handle);

        if (result == 0) {
            hContext = handle;
        }
    }

    byte[] cmdBuf = new byte[768];

    //OSAP
    System.UInt32 outSize;

    byte[] oddOsap = new byte[20];
    byte[] evenOsap = new byte[20];
    byte[] nonceEven = new byte[20];
    byte[] nonceOdd = new byte[20];
    System.UInt32 hAuth = 0;

    offset = 0;
    AddUInt16Reversed (cmdBuf, 0x00C1, ref offset);
    offset = 6;
    AddUInt32Reversed (cmdBuf, 0x0000000B, ref offset);

    offset = 2 + 4 + 4; //2 for tag, 4 for size and 4 for command code

    AddUInt16Reversed (cmdBuf, 0x0004, ref offset); //Entity Type SRK = 0x0004
    AddUInt32Reversed (cmdBuf, 0x40000000, ref offset); //Entity Value SRK = 0x40000000
    rnd.NextBytes (oddOsap);
    AddBlob (cmdBuf, oddOsap, ref offset);
    uint cmdSize = (System.UInt32) offset;
    offset = 2;
    AddUInt32Reversed (cmdBuf, cmdSize, ref offset);

    outSize = (System.UInt32) (Marshal.SizeOf (hAuth) + nonceEven.Length + evenOsap.Length);

    byte[] response = new byte[outSize];
    unsafe {
        UInt32 result = 0;

        //uint cmdSize = (uint)offset;
        uint resSize = outSize;
        fixed (byte * pCmd = cmdBuf, pRes = response) {
            result = Tbsip_Submit_Command (hContext, 0, 200, pCmd, cmdSize, pRes, & resSize);
        }
    }

    byte contSession = 0;
    System.UInt32 hKey = 0x40000000; //TPM_KH_SRK;
    System.UInt32 pcrInfoSize = 0;
    byte[] srkAuthdata = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
    uint inDataSize = (uint) plaintext.Length;

    offset = 2 + 4 + 4; //2 for tag, 4 for size and 4 for return code
    byte[] hauthbytes = new byte[Marshal.SizeOf (hAuth)];
    Array.Copy (response, offset, hauthbytes, 0, hauthbytes.Length);
    Array.Reverse (hauthbytes);
    hAuth = System.BitConverter.ToUInt32 (hauthbytes, 0);
    offset += Marshal.SizeOf (hAuth);
    Array.Copy (response, offset, nonceEven, 0, nonceEven.Length);
    offset += nonceEven.Length;
    Array.Copy (response, offset, evenOsap, 0, evenOsap.Length);

    //shared-secret = HMAC(srk_auth, even_osap || odd_osap)
    byte[] sharedSecretBuf = new byte[evenOsap.Length + oddOsap.Length];
    Array.Copy (evenOsap, 0, sharedSecretBuf, 0, evenOsap.Length);
    Array.Copy (oddOsap, 0, sharedSecretBuf, evenOsap.Length, oddOsap.Length);
    System.Security.Cryptography.HMACSHA1 sharedSecretHmac = new System.Security.Cryptography.HMACSHA1 (srkAuthdata);
    byte[] sharedSecret = sharedSecretHmac.ComputeHash (sharedSecretBuf);

    byte[] authSha1InBuf = new byte[sharedSecret.Length + nonceEven.Length];
    Array.Copy (sharedSecret, 0, authSha1InBuf, 0, sharedSecret.Length);
    Array.Copy (nonceEven, 0, authSha1InBuf, sharedSecret.Length, nonceEven.Length);
    System.Security.Cryptography.SHA1Managed sha1 = new System.Security.Cryptography.SHA1Managed ();
    byte[] authSha1 = sha1.ComputeHash (authSha1InBuf);
    byte[] encAuth = Xor (srkAuthdata, authSha1);

    //inParamDigest = sha1(1S ~ 6S) 
    int paramInDigestInBufSize =
        sizeof (System.UInt32) + 
        encAuth.Length +
        Marshal.SizeOf (pcrInfoSize) +
        Marshal.SizeOf (inDataSize) +
        (int) inDataSize;
    byte[] paramInDigestInBuf = new byte[paramInDigestInBufSize];
    offset = 0;
    AddUInt32Reversed (paramInDigestInBuf, 0x00000017, ref offset);
    AddBlob (paramInDigestInBuf, encAuth, ref offset);
    AddUInt32Reversed (paramInDigestInBuf, 0x0, ref offset); //PCR info size
    AddUInt32Reversed (paramInDigestInBuf, inDataSize, ref offset);
    AddBlob (paramInDigestInBuf, plaintext, ref offset);

    byte[] paramInDigest = sha1.ComputeHash (paramInDigestInBuf);

    int pubAuthInBufSize = paramInDigest.Length + nonceEven.Length + nonceOdd.Length + Marshal.SizeOf (contSession);
    byte[] pubAuthInBuf = new byte[pubAuthInBufSize];

    offset = 0;
    AddBlob (pubAuthInBuf, paramInDigest, ref offset);
    AddBlob (pubAuthInBuf, nonceEven, ref offset);
    AddBlob (pubAuthInBuf, nonceOdd, ref offset);
    AddBool (pubAuthInBuf, contSession, ref offset);
    System.Security.Cryptography.HMACSHA1 pubAuthHmac = new System.Security.Cryptography.HMACSHA1 (sharedSecret);
    byte[] pubAuth = pubAuthHmac.ComputeHash (pubAuthInBuf);

    //Seal
    offset = 0;
    AddUInt16Reversed (cmdBuf, 0x00C2, ref offset); // TPM_TAG_RQU_AUTH1_COMMAND;
    offset = 6;
    AddUInt32Reversed (cmdBuf, 0x00000017, ref offset); // TPM_ORD_SEAL;
    offset = 2 + 4 + 4; //2 for tag, 4 for size and 4 for command code

    AddUInt32Reversed (cmdBuf, hKey, ref offset);
    AddBlob (cmdBuf, encAuth, ref offset);
    AddUInt32Reversed (cmdBuf, pcrInfoSize, ref offset);
    AddUInt32Reversed (cmdBuf, inDataSize, ref offset);
    AddBlob (cmdBuf, plaintext, ref offset);

    AddUInt32Reversed (cmdBuf, hAuth, ref offset);
    AddBlob (cmdBuf, nonceOdd, ref offset);
    AddBool (cmdBuf, contSession, ref offset);
    AddBlob (cmdBuf, pubAuth, ref offset);
    cmdSize = (System.UInt32) offset;
    offset = 2;
    AddUInt32Reversed (cmdBuf, cmdSize, ref offset);

    outSize = 768;
    uint responseSize = 0;

    response = new byte[outSize];
    unsafe {
        UInt32 result = 0;

        uint resSize = outSize;
        fixed (byte * pCmd = cmdBuf, pRes = response) {
            result = Tbsip_Submit_Command (hContext, 0, 200, pCmd, cmdSize, pRes, & resSize);
        }
        responseSize = resSize;
    }

    byte[] retBuffer = new byte[responseSize - 10];
    Array.Copy (response, 10, retBuffer, 0, retBuffer.Length);
    Tbsip_Context_Close (hContext);
    return retBuffer;

}

Phân tích mã:

[DllImport ("tbs.dll")]
...

Đây là một số chức năng có sẵn trong Tbs.h và những chức năng duy nhất chúng tôi sẽ sử dụng ở đây. Về cơ bản, chúng cho phép bạn mở một tay cầm của thiết bị và giao tiếp với nó bằng cách gửi và nhận các byte thô.

    void AddUInt32Reversed (byte[] a, System.UInt32 o, ref int i) { ... }
    void AddUInt16Reversed (byte[] a, System.UInt16 o, ref int i) { ... }
    void AddBool (byte[] a, byte b, ref int i) { ... }
    void AddBlob (byte[] a, byte[] b, ref int i) { ... }

TPM là endian lớn, Windows là endian nhỏ. Vì vậy, thứ tự byte sẽ phải được đảo ngược đối với bất kỳ dữ liệu nào mà chúng tôi đang gửi qua. Chúng ta chỉ cần lo lắng về việc đảo ngược các int 32-bit và 16-bit không dấu ở đây.

    ...
    UInt32 result = Tbsi_Context_Create ( & version, & handle);
    ...

Ở đây chúng tôi sử dụng Tbsi_Context_Create () để mở một xử lý để nói chuyện với TPM. Các TBS_CONTEXT_PARAMSthông số chỉ là một struct C với một unsigned int lĩnh vực 32-bit phải được thiết lập để 1 tới nói chuyện với một TPM 1.2 dụ, và rằng những gì chúng ta đặt nó vào.

    byte[] cmdBuf = new byte[768];

Đây được chỉ định là kích thước bộ đệm tối thiểu trong Thông số kỹ thuật ứng dụng khách TPM PC . Nó sẽ là quá đủ cho nhu cầu của chúng tôi ở đây.

TPM 1.2 Spec Phần 3 cho biết như sau:

TPM_Seal requires the encryption of one parameter (“Secret”). For the
sake of uniformity with other commands that require the encryption of
more than one parameter, the string used for XOR encryption is
generated by concatenating a nonce (created during the OSAP session)
with the session shared secret and then hashing the result.

Chúng tôi cần XOR-mã hóa tham số "bí mật" này bằng cách sử dụng một nonce được tạo trong phiên OSAP. Một trong các trình điều khiển nhập lệnh Seal cũng là một điều khiển OSAP:

The authorization session handle used for keyHandle authorization.
Must be an OSAP session for this command.

Vì vậy, chúng ta cần thiết lập phiên OSAP này trước. OSAP được mô tả trong TPM 1.2 Spec Part 1 . OSAP, hoặc Giao thức ủy quyền đối tượng cụ thể, được phát minh để xử lý trường hợp sử dụng trong đó bạn muốn sử dụng đối tượng TPM yêu cầu ủy quyền nhiều lần, nhưng không muốn cung cấp ủy quyền mỗi lần: một phiên OSAP được sử dụng thay thế, về khái niệm "bí mật được chia sẻ", là một HMAC kết hợp dữ liệu ủy quyền đối tượng với các ký tự khác được tạo ở mỗi bên để ngăn chặn các cuộc tấn công trả lời. Do đó, "bí mật được chia sẻ" chỉ có hai bên được biết trong phiên này: bên bắt đầu phiên (người dùng) và bên chấp nhận nó (TPM); ngoài ra, cả hai bên phải có cùng dữ liệu ủy quyền đối tượng cho "bí mật được chia sẻ" là như nhau; ngoài ra, "bí mật được chia sẻ" được sử dụng trong một phiên sẽ không hợp lệ trong phiên khác. Sơ đồ này từ thông số mô tả quá trình:

OSAP

Chúng tôi sẽ không sử dụng nhiều phiên trong trường hợp cụ thể này (trên thực tế, tham số đó bị bỏ qua với lệnh Seal!) Và khóa chúng tôi sẽ sử dụng không yêu cầu ủy quyền, nhưng tiếc là chúng tôi vẫn bị ràng buộc bởi thông số kỹ thuật để thiết lập OSAP phiên họp.

    offset = 0;
    AddUInt16Reversed (cmdBuf, 0x00C1, ref offset);
    offset = 6;
    AddUInt32Reversed (cmdBuf, 0x0000000B, ref offset);

    offset = 2 + 4 + 4; //2 for tag, 4 for size and 4 for command code

    AddUInt16Reversed (cmdBuf, 0x0004, ref offset); //Entity Type SRK = 0x0004
    AddUInt32Reversed (cmdBuf, 0x40000000, ref offset); //Entity Value SRK = 0x40000000
    rnd.NextBytes (oddOsap);
    AddBlob (cmdBuf, oddOsap, ref offset);
    uint cmdSize = (System.UInt32) offset;

Toán hạng lệnh TPM_OSAP là:

Toán hạng TPM_OSAP

Mỗi lệnh TPM 1.2 được sắp xếp như sau:

  2 bytes       4 bytes             4 bytes
+---------+------------------+------------------+---------------------------
|   Tag   |       Size       |   Command code   |    Command body    ....
+---------+------------------+------------------+---------------------------

Thẻ là một giá trị hai byte cho biết liệu những gì sau đó là đầu vào hay đầu ra và liệu có bất kỳ giá trị dữ liệu xác thực nào theo sau các tham số lệnh hay không. Đối với TPM_OSAP, thẻ phải là TPM_TAG_RQU_COMMAND (0x00C1) theo thông số, có nghĩa là "lệnh không có ủy quyền".

Kích thước là một giá trị bốn byte chỉ định kích thước của lệnh tính bằng byte, bao gồm cả thẻ và kích thước của chính nó. Chúng tôi sẽ đặt giá trị này sau, khi chúng tôi đã tính toán nó.

Mã lệnh là một giá trị bốn byte mà máy chủ làm ID lệnh: nó cho TPM biết cách diễn giải phần còn lại của lệnh. Mã lệnh của chúng tôi ở đây là TPM_OSAP (0x0000000B).

Hai thứ tiếp theo cần đặt là loại thực thể và giá trị thực thể. Vì chúng tôi muốn sử dụng khóa đã tồn tại trong TPM, chúng tôi sẽ sử dụng loại thực thể "SRK" (0x0004) và vì chúng tôi đang làm việc với giả định rằng TPM đã được sở hữu, nên có thể an toàn khi cho rằng nó đã SRK được tải dưới xử lý vĩnh viễn 0x40000000 theo thông số kỹ thuật, vì vậy chúng tôi sẽ sử dụng giá trị xử lý vĩnh viễn này cho giá trị thực thể của chúng tôi. (SRK là viết tắt của "Khoá gốc lưu trữ" và là khoá gốc mà từ đó hầu hết các khoá do TPM sở hữu khác bắt nguồn)

    result = Tbsip_Submit_Command (hContext, 0, 200, pCmd, cmdSize, pRes, & resSize);

Cuối cùng, chúng tôi tính toán kích thước lệnh và đặt nó, và gửi lệnh.

    offset = 2 + 4 + 4; //2 for tag, 4 for size and 4 for return code
    byte[] hauthbytes = new byte[Marshal.SizeOf (hAuth)];
    Array.Copy (response, offset, hauthbytes, 0, hauthbytes.Length);
    Array.Reverse (hauthbytes);
    hAuth = System.BitConverter.ToUInt32 (hauthbytes, 0);
    offset += Marshal.SizeOf (hAuth);
    Array.Copy (response, offset, nonceEven, 0, nonceEven.Length);
    offset += nonceEven.Length;
    Array.Copy (response, offset, evenOsap, 0, evenOsap.Length);

Dữ liệu chúng tôi phải lấy lại từ TPM trên TPM_OSAP là:

Phản hồi TPM_OSAP

Vì vậy, chúng tôi nhận được trở lại:

  • Xử lý ủy quyền để sử dụng với lệnh chính của chúng tôi (Con dấu)
  • nonceEven: nonce do TPM tạo ra để sử dụng với lệnh chính
  • nonceEvenOSAP: OSAP nonce là bản sao đối với nonce mà chúng tôi đã tạo trước khi gửi lệnh TPM_OSAP. Hai nút này sẽ được sử dụng để tạo "bí mật được chia sẻ".

Chúng tôi trích xuất các giá trị đó và lưu trữ chúng trong các biến.

    byte[] sharedSecretBuf = new byte[evenOsap.Length + oddOsap.Length];
    Array.Copy (evenOsap, 0, sharedSecretBuf, 0, evenOsap.Length);
    Array.Copy (oddOsap, 0, sharedSecretBuf, evenOsap.Length, oddOsap.Length);
    System.Security.Cryptography.HMACSHA1 sharedSecretHmac = new System.Security.Cryptography.HMACSHA1 (srkAuthdata);
    byte[] sharedSecret = sharedSecretHmac.ComputeHash (sharedSecretBuf);

Sau đó, chúng tôi tính toán "bí mật được chia sẻ". Theo thông số kỹ thuật, các giá trị đi vào phép tính là hai ký tự không OSAP (một do người dùng tạo và một do TPM tạo) và giá trị ủy quyền cho khóa chúng ta muốn sử dụng - SRK. Theo quy ước, giá trị SRK auth là "auth nổi tiếng": một bộ đệm 20 byte được xóa bằng 0. Về mặt kỹ thuật, người ta có thể thay đổi giá trị này thành giá trị khác khi nắm quyền sở hữu TPM, nhưng điều này không được thực hiện trên thực tế, vì vậy chúng ta có thể yên tâm cho rằng giá trị "auth nổi tiếng" là tốt.

Tiếp theo, hãy xem những gì đi vào lệnh TPM_Seal:

TPM_Seal

Hầu hết các tham số này là nhỏ để xây dựng, ngoại trừ hai trong số chúng: encAuthpubAuth. Hãy xem xét từng cái một.

encAuthlà "AuthData được mã hóa cho dữ liệu được niêm phong." AuthData của chúng tôi ở đây là "auth nổi tiếng" từ trước, nhưng có, chúng tôi vẫn phải mã hóa nó. Vì chúng tôi đang sử dụng phiên OSAP nên phiên này được mã hóa theo ADIP, hoặc Giao thức chèn dữ liệu ủy quyền. Từ thông số kỹ thuật: "ADIP cho phép tạo các thực thể mới và chèn an toàn AuthData thực thể mới. Việc truyền AuthData mới sử dụng mã hóa bằng khóa dựa trên bí mật được chia sẻ của một phiên OSAP." Ngoài ra: "Đối với thuật toán mã hóa XOR bắt buộc, người tạo xây dựng khóa mã hóa bằng cách sử dụng hàm băm SHA-1 của bí mật được chia sẻ OSAP và không có phiên. Người tạo XOR mã hóa AuthData mới bằng cách sử dụng khóa mã hóa làm bảng điều khiển một lần và gửi dữ liệu được mã hóa này cùng với yêu cầu tạo tới TPM. "

Sơ đồ sau giải thích cách ADIP hoạt động:

ADIP

pubAuthlà "Thông báo phiên ủy quyền cho đầu vào và keyHandle." Phần 1 của thông số kỹ thuật, trong "Khai báo tham số cho ví dụ OIAP và OSAP" giải thích cách diễn giải bảng tham số TPM_Seal ở trên: "Cột HMAC # nêu chi tiết các tham số được sử dụng trong phép tính HMAC. Các tham số 1S, 2S, v.v. được nối và băm thành inParamDigest hoặc outParamDigest, được gọi ngầm là 1H1 và có thể là 1H2 nếu có hai phiên ủy quyền. Đối với phiên đầu tiên, 1H1, 2H1, 3H1 và 4H1 được nối và HMAC'ed. Đối với phiên thứ hai, 1H2, 2H2, 3H2, và 4H2 được nối tiếp và HMAC'ed. " Vì vậy, chúng tôi sẽ phải băm văn bản rõ ràng, kích thước của nó, kích thước thông tin PCR, encAuthtừ phía trên và thứ tự TPM_Seal, sau đó HMAC với hai phím khác và boolean "tiếp tục phiên" bằng cách sử dụng OSAP "

Đặt tất cả lại với nhau trong một sơ đồ:

Tính toán pubAuth

Lưu ý cách chúng tôi đặt "kích thước thông tin PCR" thành 0 trong mã này, vì chúng tôi chỉ muốn mã hóa dữ liệu mà không khóa nó ở trạng thái hệ thống. Tuy nhiên, việc cung cấp cấu trúc "thông tin PCR" nếu cần là rất nhỏ.

    offset = 0;
    AddUInt16Reversed (cmdBuf, 0x00C2, ref offset); 
    offset = 6;
    AddUInt32Reversed (cmdBuf, 0x00000017, ref offset); // TPM_ORD_SEAL;
    ...
    result = Tbsip_Submit_Command (hContext, 0, 200, pCmd, cmdSize, pRes, & resSize);

Cuối cùng, chúng tôi xây dựng lệnh và gửi nó.

    byte[] retBuffer = new byte[responseSize - 10];
    Array.Copy (response, 10, retBuffer, 0, retBuffer.Length);
    Tbsip_Context_Close (hContext);
    return retBuffer;

Chúng tôi sử dụng hàm Tbsip_Context_Close () để đóng xử lý giao tiếp của chúng tôi.

Chúng tôi trả lại phản hồi như hiện tại. Lý tưởng nhất là bạn muốn đảo ngược các byte một lần nữa và xác thực nó bằng cách tính toán lại resAuthgiá trị để ngăn chặn các cuộc tấn công man-in-the-middle.


Điều khó hiểu là không có lệnh Tspi_Data_Bind.

Điều này là do Tspi_Data_Bind là lệnh TSS, không phải là lệnh TPM. Lý do tại sao là bởi vì nó không yêu cầu bí mật (chỉ sử dụng khóa công khai) nên nó có thể được thực hiện mà không cần đến TPM. Tuy nhiên, điều này đã gây ra sự nhầm lẫn và ngay cả các lệnh không yêu cầu bí mật cũng được đưa vào thông số kỹ thuật TPM 2.

Làm cách nào để mã hóa khóa bằng khóa công khai của TPM?

Phụ thuộc vào phiên bản TPM. Với lệnh TPM_CreateWrapKey cho TPM 1.2. Với lệnh TPM2_Create cho TPM 2.

Làm thế nào để một nhà phát triển khóa một chìa khóa cho TPM?

Tạo nó trong TPM hoặc bọc nó hoặc sử dụng bất kỳ phương pháp nào khác có sẵn.

TPM2_Create, chỉ định một khóa HMAC

Văn bản trong cuốn sách là khó hiểu. Bạn không chỉ định khóa HMAC , bạn chỉ định rằng bạn muốn có khóa HMAC .

Thực tế là khóa HMAC không phải là bí mật có ý nghĩa

Không, nó không có ý nghĩa. Chìa khóa là bí mật.

... sử dụng các phím trong khi vẫn giữ chúng an toàn trong thiết bị phần cứng ... Tuyệt vời! Bạn làm nó như thế nào!?

Có các lệnh để tạo khóa hoặc nhập chúng cho cả hai phiên bản TPM. Đối với TPM 1, chỉ có một khóa gốc - SRK - từ đó bạn có thể thiết lập hệ thống phân cấp khóa bằng cách tạo các khóa được bọc. Với TPM 2, bạn có thể có nhiều khóa chính hoặc khóa gốc.

TPM có khả năng tạo khóa mật mã và bảo vệ bí mật của nó trong ranh giới phần cứng không? Là như vậy, làm thế nào?

Xem ở trên.

Thông minh! Đây chính xác là trường hợp sử dụng mà tôi muốn. Đây cũng là trường hợp sử dụng mà Microsoft sử dụng TPM. Tôi phải làm nó như thế nào!?

Có lẽ phụ thuộc vào loại ổ đĩa. Trong trường hợp ổ đĩa không phải SED, khóa mã hóa ổ đĩa có thể được bọc bằng khóa TPM. Trong trường hợp ổ đĩa SED, mật khẩu Admin1 (hoặc mật khẩu tương tự) được niêm phong bằng TPM.

Khóa xác nhận hoặc EK ... Ở đâu đó bên trong TPM là khóa riêng RSA. Chìa khóa đó được khóa trong đó - không bao giờ bị thế giới bên ngoài nhìn thấy. Tôi muốn TPM ký một cái gì đó bằng khóa riêng của nó (tức là mã hóa nó bằng khóa riêng của nó).

EK không phải là khóa ký - mà là khóa mã hóa. Tuy nhiên, nó không phải là một khóa mã hóa có mục đích chung: nó chỉ có thể được sử dụng trong một số ngữ cảnh nhất định .

Nhưng điều tôi thực sự muốn làm là "niêm phong" một số dữ liệu

Xem ở trên.


2

Khi nó nói

chỉ định khóa HMAC

nó KHÔNG có nghĩa là cung cấp khóa HMAC - nó có nghĩa là "trỏ đến khóa HMAC mà bạn muốn sử dụng" .

TPM có thể sử dụng số lượng khóa HMAC hầu như không giới hạn, như được chỉ ra trong cuốn sách. Bạn phải cho TPM biết nên sử dụng cái nào.


Vì vậy, có lẽ có một mẫu mã hiển thị cách chỉ định (trỏ tới) khóa HMAC sẽ được sử dụng trong C # hoặc ngôn ngữ khác không?
Chad
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.