Chương 1:
Giới thiệu chung về CSP
(Cryptographic Service Providers)
CSP là thuật ngữ để chỉ một thành phần trong hệ điều hành Microsoft Windows chứa cài
đặt của các thuật toán và chuẩn mật mã. Một CSP tối thiểu phải có một thư viện dạng liên
kết động (DLL) làm nhiệm vụ hiện thực hóa các hàm trong CryptoSPI (interface giao tiếp
giữa CSP và hệ thống). Hầu hết các CSP tự hiện thực hóa các hàm chức năng của nó. Cũng
có một số CSP sử dụng các dịch vụ của Windows để thực hiện các hàm riêng của mình
dưới sự quản lí của Windows Service Control Manager. Một số CSP khác cài đặt các hàm
này ở mức phần cứng, chẳng hạn như smart-card, pki-token… Nếu một CSP không hiện
thực tất cả các hàm chức năng cần thiết, nó sẽ hoạt động như là một lớp trung gian, đảm
bảo giao tiếp giữa hệ điều hành và chi tiết cài đặt thực sự của các hàm ở lớp bên dưới
(hardware).
1. Tổng quan kiến trúc CSP
Các ứng dụng liên quan tới mật mã chạy trên Windows không giao tiếp trực tiếp với các
CSP mà thông qua việc gọi các hàm trong giao diện CryptoAPI. Các hàm này được cung
cấp trong các thư viện động Advapi32.dll và Crypt32.dll. Sau đó, tới lượt các API này làm
nhiệm vụ tách lọc và chuyển thông tin từ ứng dụng đến CSP thông qua các hàm trong giao
diện CryptoSPI.
1
Các ứng dụng truy xuất data trong CSP thông qua handle của các đối tượng. Mỗi đối tượng
bao gồm key-container, hash-object, session-key và cặp public-private key.
1.1 Giao diện CryptoSPI
Tất cả các CSP phải hỗ trợ các entry-point sau trong DLL của nó:
* CPAcquireContext
Hàm này làm nhiệm vụ lấy handle của key-container được chỉ đến trong tham số
pszContainer.
BOOL CPAcquireContext(
__out HCRYPTPROV *phProv,
__in CHAR *pszContainer,
__in DWORD dwFlags,
__in ALG_ID Algid,
__in HCRYPTHASH hBaseData,
__in DWORD dwFlags,
__out HCRYPTKEY *phKey
);
* CPDestroyHash
Hủy đối tượng hash đã được chỉ ra trong tham số hHash.
BOOL CPDestroyHash(
__in HCRYPTPROV hProv,
__in HCRYPTHASH hHash
);
* CPDestroyKey
Giải phóng handle được chỉ ra trong tham số hKey. Sau khi giải phóng handle của một
khóa, khóa đó sẽ không còn hợp lệ và không sử dụng được nữa.
BOOL CPDestroyKey(
__in HCRYPTPROV hProv,
__in HCRYPTKEY hKey
);
* CPEncrypt
Hàm này làm nhiệm vụ mã hóa dữ liệu. Có thể tùy chọn băm dữ liệu đầu ra.
BOOL CPEncrypt(
__in HCRYPTPROV hProv,
__in HCRYPTKEY hKey,
__in HCRYPTHASH hHash,
__in BOOL Final,
__in DWORD dwFlags,
__inout BYTE *pbData,
__inout DWORD *pdwDataLen,
__in DWORD dwBufLen
);
BOOL CPGetHashParam(
__in HCRYPTPROV hProv,
__in HCRYPTHASH hHash,
__in DWORD dwParam,
__out BYTE *pbData,
__inout DWORD *pdwDataLen,
__in DWORD dwFlags
);
* CPGetKeyParam
Trích xuất dữ liệu về các tham số của một khóa.
BOOL CPGetKeyParam(
__in HCRYPTPROV hProv,
__in HCRYPTKEY hKey,
__in DWORD dwParam,
__out LPBYTE pbData,
__inout LPDWORD pcbDataLen,
__in DWORD dwFlags
);
* CPGetProvParam
Trả về thông tin của CSP
BOOL CPGetProvParam(
__in HCRYPTPROV hProv,
__in DWORD dwParam,
__out BYTE *pbData,
__inout DWORD *pdwDataLen,
4
__in DWORD dwFlags
);
* CPGetUserKey
Trích xuất hanlde của các cặp khóa chứa trong key-container được chỉ ra trong tham số
__in HCRYPTKEY hPubKey,
__in DWORD dwFlags,
__out HCRYPTKEY *phKey
);
* CPReleaseContext
Giải phóng một context được tạo ra trước đó bởi hàm CPAcquireContext.
BOOL CPReleaseContext(
__in HCRYPTPROV hProv,
5
__in DWORD dwFlags
);
* CPSetHashParam
Tùy chỉnh hoạt động của một đối tượng hash.
BOOL CPSetHashParam(
__in HCRYPTPROV hProv,
__in HCRYPTHASH hHash,
__in DWORD dwParam,
__in BYTE *pbData,
__in DWORD dwFlags
);
* CPSetKeyParam
Tùy chỉnh hoạt động của một khóa.
BOOL CPSetKeyParam(
__in HCRYPTPROV hProv,
__in HCRYPTKEY hKey,
__in DWORD dwParam,
__in BYTE *pbData,
__in DWORD dwFlags
);
* CPSetProvParam
Các hàm trên hợp thành giao diện giao tiếp CryptoSPI giữa system-layer và CSP-layer.
Mỗi hàm tương ứng trực tiếp với một hàm trong giao diện CryptoAPI.
Các đối tượng bền vững (persistent data objects)
Một CSP có thể lưu các cặp khóa pb/pr để sử dụng cho nhiều session trong một bộ nhớ bền
vững. Nếu là dạng thuần software CSP thì có thể lưu trữ dưới dạng mã hóa trong registry.
Nếu CSP có chứa thành phần hardware khác thì có thể lưu trữ trong các bộ nhớ được bảo
vệ của hardware đó.
Các cặp khóa được lưu dưới dạng đối tượng logic gọi là key-container. CSP sẽ quản lí mỗi
key-container cho một client sử dụng CSP đó. Mỗi key-container có thể chứa nhiều cặp
khóa tương ứng với từng loại mà CSP hỗ trợ. Chẳng hạn Microsoft Base Cryptographic
Provider hỗ trợ 2 loại cặp khóa: lọai cặp dùng để trao đổi khóa (key exchange key pair) và
loại cặp dùng để tạo chữ kí (digital signature key pair).
Tại một thời điểm, mỗi key-container có thể được sử dụng bởi nhiều chương trình ứng
dụng. Mỗi lời gọi tới một hàm trong CryptoSPI đều chỉ ra các tham số áp dụng cho key-
container trong hàm đó, như thể hiện trong sơ đồ dưới:
Đối với giao diện CryptoSPI, HCRYPTPROV là handle của một key-container cụ thể
trong CSP. Tuy nhiên, đối với giao diện CryptoAPI, HCRYPTPROV là handle cho cả key-
container và cả CSP đang được sử dụng.
7
Các đối tượng không bền vững (volatile data objects)
Một CSP quản lí các đối tượng session-key và hash-object trong bộ nhớ không bền vững.
Các đối tượng này được tạo bởi hàm CPGenKey và CPCreateHash, được hủy bởi các hàm
CPDestroyKey và CPDestroyHash. Các đối tượng trên phải được hủy khi key-container
tương ứng được hủy thông qua hàm CPReleaseContext.
Các đối tượng trong bộ nhớ không bền vững được truy cập thông qua các handle như hình
dưới:
1.2 Các loại Cryptographic Provider
Ngày càng có nhiều chuẩn mã hóa dữ liệu cũng như các giao thức giao tiếp khác nhau.
Chúng được phân loại thành các nhóm, mỗi nhóm có đặc tính riêng về cách tổ chức định
dạng dữ liệu và cách tiến hành các thuật toán. Thậm chí nếu hai nhóm dùng chung một
động khóa công khai.
Key Exchange RSA
Signature RSA
Encryption RC2, RC4
Hashing MD5, SHA
* PROV_RSA_AES
Cung cấp cả cơ chế chữ kí số cũng như mã hóa dữ liệu, có thể sử dụng cho tất cả hoạt
động khóa công khai.
Key Exchange RSA
Signature RSA
Encryption RC2, RC4, Advanced Encryption Standard (AES)
Hashing MD2, MD4, MD5, SHA-1, SHA-2 (SHA-256, SHA-384, SHA-512)
* PROV_RSA_SIG
Tập con của PROV_RSA_FULL, chỉ hỗ trợ các thuật toán băm và chữ kí điện tử
Key Exchange None
Signature RSA
Encryption None
Hashing MD5, SHA
* PROV_RSA_SCHANNEL
Hỗ trợ cả thuật toán RSA và Schannel
Key Exchange RSA
Signature RSA
Encryption Một trong số: RC4, DES, Triple DES
Hashing MD5, SHA
* PROV_DSS
Chỉ hỗ trợ băm và chữ kí điện tử
Key Exchange None
Signature DSS
Encryption None
Hashing MD5, SHA
Signature RSA
Encryption Tùy thuộc
Hashing Tùy thuộc
Ngoài ra, các nhà phát triển CSP có thể tự định nghĩa kiểu cho riêng mình.
10
1.3 Các CSP được cung cấp bởi Microsoft
Hiện tại Microsoft cung cấp các CSP sau:
Provider Description
Microsoft Base Cryptographic
Provider
Cung cấp các hàm chức năng mật mã cơ bản.
Microsoft Strong Cryptographic
Provider
Phiên bản mở rộng, áp dụng từ Windows 2000.
Microsoft Enhanced Cryptographic
Provider
Áp dụng chiều dài khóa lớn hơn, bổ sung thêm một
số thuật toán.
Microsoft AES Cryptographic
Provider
Mở rộng của bản Enhanced, hỗ trợ thuật toán mã
hóa AES.
Microsoft DSS Cryptographic
Provider
Cung cấp cơ chế băm, kí và kiểm chứng chữ kí sử
dụng chuẩn SHA và DSS.
Microsoft Base DSS and Diffie-
Hellman Cryptographic Provider
Bản mở rộng của DSS, hỗ trợ thuật toán trao đổi
khóa Dfiie-Hellman.
Cho trước một key, các CSP phải đảm bảo hash ra được cùng một
giá trị.
Digital signature
mechanics
Các CSP phải có cùng cơ chế phát sinh chữ kí điện tử để có thể
kiểm chứng lẫn nhau.
1.5 Quá trình viết các CSP
Trước khi viết CSP cụ thể, nhà phát triển phải chọn trước và hiện thực hóa các thuật toán
mã hoá cũng như định dạng dữ liệu sẽ được đưa vào. Quá trình phát triển một CSP bao
gồm các bước như sau:
1/ Tạo thư viện động (DLL ) hiện thực các hàm.
Quá trình tạo các dll được thực hiện bởi CSP developer’s toolkit. Với các CSP có chứa
thành phần hardware, trong dll phải chứa driver để điều khiển thành phần này. Trong dll
cần hiện thực các hàm của giao diện CryptoSPI đã nói ở phần trước.
2/ Viết chương trình cài đặt CSP.
Chương trình này làm nhiệm vụ sao chép dll vào thư mục cụ thể (trỏ tới bởi biến môi
trường PATH), cũng như tạo các khóa cần thiết trong registry.
3/ Kiểm chứng hoạt động của CSP
4/ Kí CSP
Một CSP phải được kí bởi Microsoft để có thể sử dụng được trong các hệ điều hành
Windows
5/ Kiểm tra lại hoạt động của CSP sau khi được kí
12
Chương 2:
Smart Card CSP
Một trường hợp đặc biệt và khá thông dụng của CSP đó là Smart Card CSP. Đó là sự kết
hợp giữa các lớp middle-ware và hardware để phục vụ nhu cầu kí, giao dịch an toàn và các
dịch vụ mật mã khác.
2.1 Tổng quan về Smart Card CSP
Smart Card thường có hai dạng, có thể dưới dạng các thẻ plastic, có thể dưới dạng USB
CryptoAPI Flag Hardware CSP Software CSP
CryptAcquireContext CRYPT_SILENCE
Tắt tất cả các giao
tiếp UI với thẻ, kể
cả các UI để nhập
PIN
Tắt các UI đang yêu
cầu xác nhận
password bảo vệ
khóa
CryptAcquireContext CRYPT_MACHINE_KEY_SET
Không cache bất
cứ thông tin nào
thông qua handle
trả về của hàm
Tạo các khóa có thể
chia sẽ bởi nhiều
người trên cùng một
máy. Không lưu trữ
khóa trong user
14
profile
CryptAcquireContext CRYPT_VERIFYCONTEXT
Chỉ cho phép CSP
truy cập dữ liệu
công cộng trên
hardware
Cho phép hoạt động
truy cập bất kì
CryptExportKey
thực mã PIN của người dùng sau mỗi phiên giao dịch. Tuy nhiên, điều này lại gây phiền
toái cho người sử dụng khi phải nhập PIN liên tục cho mỗi lần giao dịch. Do đó, người
phát triển CSP phải cung cấp cơ chế lưu trữ PIN tạm thời một cách an toàn (PIN caching).
PIN sẽ được lưu trữ trong bộ nhớ của CSP, tương ứng cho từng process, đồng thời gắn với
Logon ID của người dùng. Mỗi thẻ cũng sẽ có một vùng cache riêng, CSP sẽ xác định
process nào trong cache của thẻ nào trong phiên làm việc của user nào có mã PIN hợp lệ.
CSP có thể lấy PIN từ người dùng (thông qua PIN UI) hoặc từ ứng dụng (thông qua hàm
CryptSetProvParam PP_KEYEXCHANGE). Sau đó, mã này được đưa xuống thẻ để xác
15
thực, đồng thời được cập nhật vào cache để đảm bảo đồng bộ hóa. CSP phải xóa bỏ cache
khi process kết thúc, khi người dùng thoát, hoặc khi thẻ được gỡ khỏi máy.
Hai hình dưới là quá trình PIN caching tương ứng với hai trường hợp lấy mã từ user đã đề
cập ở trên:
16
2.3 Một số quá trình xác thực thông dụng
Phần này trình bày các bước gọi hàm cũng như các tham số và flag được sử dụng trong các
quá trình thường gặp với thẻ.
Windows XP interactive logon
1. CryptAcquireContext
Lấy handle chỉ tới key-container mặc định, sử dụng 2 flag CRYPT_MACHINE_KEYSET
và CRYPT_SILENT
2. CryptGetUserKey
Lấy handle chỉ tới khóa trao đổi khóa của người dùng
3. CryptGetKeyParam
17
Lấy thông số kích thước của certificate (byte)
4. CryptGetKeyParam
Đọc certificate từ thẻ vào buffer
5. CryptGetProvParam
Sử dụng cờ PP_CONTAINER để lấy kích cỡ của tên của key-container hiện tại
19. CryptGetHashParam
Sử dụng tham số HP_HASHVAL để lấy kích thước của mã hash
20. CryptGetHashParam
Lấy giá trị đã băm
21. CryptCreateHash
Lấy handle chỉ tới một đối tượng hash sử dụng MD5
22. CryptSetHashParam
Sử dụng tham số HP_HASHVAL, không có dữ liệu vào
23. CryptSignHash
Lấy kích thước của chữ kí đã phát sinh
24. CryptSignHash
Lấy về mã băm đã được kí
25. CryptDestroyHash
Giải phóng đối tượng hash 1
26. CryptDestroyHash
Giải phóng đối tượng hash 2
27. CryptSetProvParam
Chuyển mã PIN cho thẻ
28. CryptSetProvParam
Chuyển mã PIN cho thẻ
29. CryptGetUserKey
Lấy handle chỉ tới khóa trao đổi khóa trong key-container mặc định
30. CryptImportKey
Import khóa từ bên ngoài
31. CryptSetKeyParam
Khởi tạo vector, cho tất cả giá trị về 0
32. CryptDecrypt
Giải mã đoạn dữ liệu với khóa đã import trước đó
33. CryptDestroyKey
Giải phóng khóa được import
Sử dụng cờ PP_CONTAINER để lấy kích cỡ của tên của key-container hiện tại
49. CryptGetProvParam
Lấy tên của key-container hiện tại
50. CryptGetUserKey
Lấy handle chỉ tới khóa trao đổi khóa trong key-container mặc định
51. CryptGetKeyParam
Lấy thông số kích thước của certificate (byte)
52. CryptGetKeyParam
Đọc certificate từ thẻ vào buffer
53. CryptDestroyKey
Giải phóng handle chỉ tới khóa trao đổi khóa trước đó
54. CryptGetUserKey
Lấy handle chỉ tới khóa phát sinh chữ kí trong key-container mặc định
20
55. CryptReleaseContext
Giải phóng handle chỉ tới key-container mặc định
Kí thư điện tử
Quá trình tạo chữ kí điện tử cho email trong Windows XP có các bước như sau:
1. CryptAcquireContext
Lấy handle chỉ đến key-container mặc định trên hardware
2. CryptCreateHash
Lấy handle chỉ đến một đối tượng hàm băm SHA
3. CryptHashData
Băm dữ liệu đã được đưa vào
4. CryptGetHashParam
Lấy kích cỡ mã băm, sử dụng tham số HP_HASHVAL
5. CryptGetHashParam
Lấy dữ liệu sau khi băm
6. CryptHashData
Tiếp tục băm dữ liệu đầu vào
do nhà cung cấp phát triển).
Base CSP là lớp chung, sẽ chịu trách nhiệm giao tiếp với lớp trên, quản lí các tác vụ thông
dụng như PIN cache, PIN entry, hash, mã hóa đối xứng, mã hóa khóa công cộng …
Các minidriver tương ứng với các nhà cung cấp thẻ sẽ chịu trách nhiệm quản lí các tác vụ
gắn liền với thẻ thông qua giao tiếp với lớp SCRM (smartcard resource manager) ở dưới
nhằm mục đích trừu tượng hóa các giao tiếp đặc thù của từng loại thẻ sao cho khớp với
Base CSP. Các ứng dụng liên quan tới thẻ có thể dùng CryptoAPI: Next Generation
(CNG) hoặc Key Storage Provider (KSP) để giao tiếp với các lớp bên dưới. Sơ đồ tổng
quát của hệ thống, tương ứng với các ứng dụng dùng CAPI và CAPI2 như sau:
23
3.2 Hiện thực hóa minidriver:
3.2.1 Tổng quan:
Smartcard minidriver là lớp giao diện thấp nhất trong hệ thống, giúp cho Base CSP/KSP có
thể tương tác với các loại thẻ khác nhau thông qua SCRM. Minidriver được hiện thực dưới
dạng một dll hỗ trợ các API được đề cập trong spec của Microsoft. Mỗi lời gọi tới các hàm
trong minidriver đều đi kèm tham số là một con trỏ kiểu CARD_DATA, cung cấp thông
tin về ngữ cảnh cụ thể khi giao tiếp như trạng thái kết nối, bảng con trỏ hàm… Thông số
này sẽ được gán giá trị cụ thể bởi minidriver khi lớp trên gọi tới hàm CardAcquireContext.
Mỗi hoạt động gắn với card (như là kiểm tra PIN, giải mã, kí…) được khuyến khích tiến
hành dưới dạng các atomic transaction (các chuỗi hoạt động có đặc điểm chỉ được thực
hiện tất cả, hoặc không thực hiện hoạt động nào) nhằm đảm bảo toàn vẹn dữ liệu trên thẻ.
24
3.2.2 Cấp phát bộ nhớ:
Mọi API trong minidriver nếu cần cấp phát động bộ nhớ động thì phải sử dụng hàm
PFN_CSP_ALLOC, và tương ứng là PFN_CSP_FREE để giải phóng.
3.2.3 Cache:
Lớp Card Interface trong Base CSP/KSP hiện thực một cache để giảm thiểu lượng data
ghi/đọc xuống thẻ. Minidriver có thể sử dụng các cache này thông qua các con trỏ hàm để
tăng hiệu quả hoạt động.
3.2.4 Version checking: