Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

389 lines
7.9 KiB

  1. /*++
  2. Copyright (c) 1994-1998 Microsoft Corporation
  3. Module Name:
  4. clicert.c
  5. Abstract:
  6. Contains code related to the tshare certificate validation and data
  7. encryption using server public key.
  8. Author:
  9. Madan Appiah (madana) 24-Jan-1998
  10. Environment:
  11. User Mode - Win32
  12. Revision History:
  13. --*/
  14. #include <seccom.h>
  15. BOOL
  16. UnpackServerCert(
  17. LPBYTE pbCert,
  18. DWORD dwCertLen,
  19. PHydra_Server_Cert pServerCert
  20. )
  21. /*++
  22. Routine Description:
  23. This function unpacks the blob of server certicate to server certificate
  24. structure.
  25. Arguments:
  26. pbCert - pointer to the server public key blob.
  27. dwCertLen - length of the above server public key.
  28. pServerCert - pointer to a server certificate structure.
  29. Return Value:
  30. TRUE - if successfully unpacked.
  31. FALSE - otherwise.
  32. --*/
  33. {
  34. LPBYTE pbScan;
  35. DWORD cbScan;
  36. //
  37. // return if the pointer are invalid.
  38. // return if the certificate is insufficient length.
  39. //
  40. if( (pbCert == NULL) ||
  41. (dwCertLen < (3 * sizeof(DWORD) + 4 * sizeof(WORD))) ||
  42. (pServerCert == NULL) ) {
  43. return( FALSE );
  44. }
  45. pbScan = pbCert;
  46. cbScan = dwCertLen;
  47. //
  48. // Assign dwVersion
  49. //
  50. pServerCert->dwVersion = *(DWORD UNALIGNED FAR *)pbScan;
  51. pbScan += sizeof(DWORD);
  52. cbScan -= sizeof(DWORD);
  53. //
  54. // Assign dwSigAlgID
  55. //
  56. pServerCert->dwSigAlgID = *(DWORD UNALIGNED FAR *)pbScan;
  57. pbScan += sizeof(DWORD);
  58. cbScan -= sizeof(DWORD);
  59. //
  60. // Assign dwSignID
  61. //
  62. pServerCert->dwKeyAlgID = *(DWORD UNALIGNED FAR *)pbScan;
  63. pbScan += sizeof(DWORD);
  64. cbScan -= sizeof(DWORD);
  65. //
  66. //Assign PublicKeyData
  67. //
  68. pServerCert->PublicKeyData.wBlobType = *(WORD UNALIGNED FAR *)pbScan;
  69. pbScan += sizeof(WORD);
  70. cbScan -= sizeof(WORD);
  71. if( pServerCert->PublicKeyData.wBlobType != BB_RSA_KEY_BLOB ) {
  72. return( FALSE );
  73. }
  74. pServerCert->PublicKeyData.wBlobLen = *(WORD UNALIGNED FAR *)pbScan;
  75. pbScan += sizeof(WORD);
  76. cbScan -= sizeof(WORD);
  77. if( pServerCert->PublicKeyData.wBlobLen > 0 ) {
  78. if(cbScan < pServerCert->PublicKeyData.wBlobLen) {
  79. return ( FALSE );
  80. }
  81. pServerCert->PublicKeyData.pBlob = pbScan;
  82. pbScan += pServerCert->PublicKeyData.wBlobLen;
  83. cbScan -= pServerCert->PublicKeyData.wBlobLen;
  84. }
  85. else {
  86. pServerCert->PublicKeyData.pBlob = NULL;
  87. }
  88. //
  89. // Assign SignatureBlob
  90. //
  91. if(cbScan < sizeof(WORD)) {
  92. return ( FALSE );
  93. }
  94. pServerCert->SignatureBlob.wBlobType = *(WORD UNALIGNED *)pbScan;
  95. pbScan += sizeof(WORD);
  96. cbScan -= sizeof(WORD);
  97. if( pServerCert->SignatureBlob.wBlobType != BB_RSA_SIGNATURE_BLOB ) {
  98. return( FALSE );
  99. }
  100. if(cbScan < sizeof(WORD)) {
  101. return ( FALSE );
  102. }
  103. pServerCert->SignatureBlob.wBlobLen = *(WORD UNALIGNED FAR *)pbScan;
  104. pbScan += sizeof(WORD);
  105. cbScan -= sizeof(WORD);
  106. if( pServerCert->SignatureBlob.wBlobLen > 0 ) {
  107. if(cbScan < pServerCert->SignatureBlob.wBlobLen) {
  108. return ( FALSE );
  109. }
  110. pServerCert->SignatureBlob.pBlob = pbScan;
  111. }
  112. else {
  113. pServerCert->SignatureBlob.pBlob = NULL;
  114. }
  115. return( TRUE );
  116. }
  117. BOOL
  118. ValidateServerCert(
  119. PHydra_Server_Cert pServerCert
  120. )
  121. /*++
  122. Routine Description:
  123. This function validate the server public key.
  124. Arguments:
  125. pSserverCert - pointer to a server certificate.
  126. Return Value:
  127. TRUE - if the server public key is valid.
  128. FALSE - otherwise.
  129. --*/
  130. {
  131. DWORD dwLen;
  132. LPBYTE pbSignature;
  133. MD5_CTX HashState;
  134. BYTE SignHash[0x48];
  135. LPBYTE pbScan;
  136. //
  137. // pack the certificate data into a byte blob excluding the signature info.
  138. //
  139. dwLen =
  140. 3 * sizeof(DWORD) +
  141. 2 * sizeof(WORD) +
  142. pServerCert->PublicKeyData.wBlobLen;
  143. //
  144. // allocated space for the binary blob.
  145. //
  146. pbSignature = malloc( (UINT)dwLen );
  147. if( pbSignature == NULL ) {
  148. return( FALSE );
  149. }
  150. pbScan = pbSignature;
  151. memcpy( pbScan, &pServerCert->dwVersion, sizeof(DWORD));
  152. pbScan += sizeof(DWORD);
  153. memcpy( pbScan, &pServerCert->dwSigAlgID, sizeof(DWORD));
  154. pbScan += sizeof(DWORD);
  155. memcpy( pbScan, &pServerCert->dwKeyAlgID, sizeof(DWORD));
  156. pbScan += sizeof(DWORD);
  157. memcpy( pbScan, &pServerCert->PublicKeyData.wBlobType, sizeof(WORD));
  158. pbScan += sizeof(WORD);
  159. memcpy( pbScan, &pServerCert->PublicKeyData.wBlobLen, sizeof(WORD));
  160. pbScan += sizeof(WORD);
  161. memcpy(
  162. pbScan,
  163. pServerCert->PublicKeyData.pBlob,
  164. pServerCert->PublicKeyData.wBlobLen);
  165. //
  166. // generate the hash on the data.
  167. //
  168. MD5Init( &HashState );
  169. MD5Update( &HashState, pbSignature, dwLen );
  170. MD5Final( &HashState );
  171. //
  172. // free the signature blob, we don't need it anymore.
  173. //
  174. free( pbSignature );
  175. //
  176. // initialize the pulic key.
  177. //
  178. g_pPublicKey = (LPBSAFE_PUB_KEY)g_abPublicKeyModulus;
  179. g_pPublicKey->magic = RSA1;
  180. g_pPublicKey->keylen = 0x48;
  181. g_pPublicKey->bitlen = 0x0200;
  182. g_pPublicKey->datalen = 0x3f;
  183. g_pPublicKey->pubexp = 0xc0887b5b;
  184. //
  185. // decrypt the signature.
  186. //
  187. memset(SignHash, 0x00, 0x48);
  188. BSafeEncPublic( g_pPublicKey, pServerCert->SignatureBlob.pBlob, SignHash);
  189. //
  190. // compare the hash value.
  191. //
  192. if( memcmp( SignHash, HashState.digest, 16 )) {
  193. return( FALSE );
  194. }
  195. //
  196. // successfully validated the signature.
  197. //
  198. return( TRUE );
  199. }
  200. BOOL
  201. EncryptClientRandom(
  202. LPBYTE pbSrvPublicKey,
  203. DWORD dwSrvPublicKey,
  204. LPBYTE pbRandomKey,
  205. DWORD dwRandomKeyLen,
  206. LPBYTE pbEncRandomKey,
  207. LPDWORD pdwEncRandomKey
  208. )
  209. /*++
  210. Routine Description:
  211. Encrypt the client random using server's public key.
  212. Arguments:
  213. pbSrvPublicKey - pointer to the server public key.
  214. dwSrvPublicKey - length of the server public key.
  215. pbRandomKey - pointer to a buffer where the client random key.
  216. dwRandomKeyLen - length of the random key passed in.
  217. pbEncRandomKey - pointer to a buffer where the encrypted client random is
  218. returned.
  219. pdwEncRandomKey - pointer to a place where the length of the above buffer is
  220. passed in and length of the buffer used/required is returned.
  221. Return Value:
  222. TRUE - if the key is encrypted successfully.
  223. FALSE - otherwise.
  224. --*/
  225. {
  226. LPBSAFE_PUB_KEY pSrvPublicKey;
  227. BYTE abInputBuffer[512];
  228. ASSERT( pbSrvPublicKey != NULL );
  229. pSrvPublicKey = (LPBSAFE_PUB_KEY)pbSrvPublicKey;
  230. //
  231. // check to see buffer length pointer is valid.
  232. //
  233. if( pdwEncRandomKey == NULL ) {
  234. return( FALSE );
  235. }
  236. //
  237. // check to see a output buffer is specified and
  238. // the encrypt buffer length is sufficient.
  239. //
  240. if( (pbEncRandomKey == NULL) ||
  241. (*pdwEncRandomKey < pSrvPublicKey->keylen) ) {
  242. *pdwEncRandomKey = pSrvPublicKey->keylen;
  243. return( FALSE );
  244. }
  245. //
  246. // make sure the random key data and its length are valid.
  247. //
  248. ASSERT( pbRandomKey != NULL );
  249. ASSERT( dwRandomKeyLen <= pSrvPublicKey->datalen );
  250. ASSERT( pSrvPublicKey->datalen < pSrvPublicKey->keylen );
  251. ASSERT( pSrvPublicKey->keylen <= sizeof(abInputBuffer) );
  252. //
  253. // init the input buffer.
  254. //
  255. memset( abInputBuffer, 0x0, (UINT)pSrvPublicKey->keylen );
  256. //
  257. // copy data to be encrypted in the input buffer.
  258. //
  259. memcpy( abInputBuffer, pbRandomKey, (UINT)dwRandomKeyLen );
  260. //
  261. // initialize the output buffer.
  262. //
  263. memset( pbEncRandomKey, 0x0, (UINT)pSrvPublicKey->keylen );
  264. //
  265. // encrypt data now.
  266. //
  267. if( !BSafeEncPublic(
  268. pSrvPublicKey,
  269. (LPBYTE)abInputBuffer,
  270. pbEncRandomKey ) ) {
  271. *pdwEncRandomKey = 0;
  272. return( FALSE );
  273. }
  274. //
  275. // successfully encrypted the client random,
  276. // return the encrypted data length.
  277. //
  278. *pdwEncRandomKey = pSrvPublicKey->keylen;
  279. return( TRUE );
  280. }