Leaked source code of windows server 2003
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.

466 lines
9.3 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. seed.c
  5. Abstract:
  6. Storage and retrieval of cryptographic RNG seed material.
  7. Author:
  8. Scott Field (sfield) 24-Sep-98
  9. --*/
  10. #ifndef KMODE_RNG
  11. #include <nt.h>
  12. #include <ntrtl.h>
  13. #include <nturtl.h>
  14. #include <zwapi.h>
  15. #include <windows.h>
  16. #else
  17. #include <ntifs.h>
  18. #include <windef.h>
  19. #endif // KMODE_RNG
  20. #include "seed.h"
  21. #include "umkm.h"
  22. BOOL
  23. AccessSeed(
  24. IN ACCESS_MASK DesiredAccess,
  25. IN OUT PHKEY phkResult
  26. );
  27. BOOL
  28. AdjustSeedSecurity(
  29. IN HKEY hKeySeed
  30. );
  31. #ifdef KMODE_RNG
  32. #define SEED_KEY_LOCATION L"\\Registry\\Machine\\SOFTWARE\\Microsoft\\Cryptography\\RNG"
  33. #define SEED_VALUE_NAME L"Seed"
  34. #ifdef ALLOC_PRAGMA
  35. #pragma alloc_text(PAGE, ReadSeed)
  36. #pragma alloc_text(PAGE, WriteSeed)
  37. #pragma alloc_text(PAGE, AccessSeed)
  38. #endif // ALLOC_PRAGMA
  39. #else
  40. #define SEED_KEY_LOCATION "SOFTWARE\\Microsoft\\Cryptography\\RNG"
  41. #define SEED_VALUE_NAME "Seed"
  42. #endif // KMODE_RNG
  43. //
  44. // globally cached registry handle to seed material.
  45. // TODO: later.
  46. //
  47. ///HKEY g_hKeySeed = NULL;
  48. BOOL
  49. ReadSeed(
  50. IN PBYTE pbSeed,
  51. IN DWORD cbSeed
  52. )
  53. {
  54. HKEY hKeySeed;
  55. #ifndef KMODE_RNG
  56. DWORD dwType;
  57. LONG lRet;
  58. #else
  59. static const WCHAR wszValue[] = SEED_VALUE_NAME;
  60. BYTE FastBuffer[ 256 ];
  61. PKEY_VALUE_PARTIAL_INFORMATION pKeyInfo;
  62. DWORD cbKeyInfo;
  63. UNICODE_STRING ValueName;
  64. NTSTATUS Status;
  65. PAGED_CODE();
  66. #endif // KMODE_RNG
  67. //
  68. // open handle to RNG registry key.
  69. //
  70. if(!AccessSeed( KEY_QUERY_VALUE, &hKeySeed ))
  71. return FALSE;
  72. #ifndef KMODE_RNG
  73. lRet = RegQueryValueExA(
  74. hKeySeed,
  75. SEED_VALUE_NAME,
  76. NULL,
  77. &dwType,
  78. pbSeed,
  79. &cbSeed
  80. );
  81. REGCLOSEKEY( hKeySeed );
  82. if( lRet != ERROR_SUCCESS )
  83. return FALSE;
  84. return TRUE;
  85. #else
  86. ValueName.Buffer = (LPWSTR)wszValue;
  87. ValueName.Length = sizeof(wszValue) - sizeof(WCHAR);
  88. ValueName.MaximumLength = sizeof(wszValue);
  89. pKeyInfo = (PKEY_VALUE_PARTIAL_INFORMATION)FastBuffer;
  90. cbKeyInfo = sizeof(FastBuffer);
  91. Status = ZwQueryValueKey(
  92. hKeySeed,
  93. &ValueName,
  94. KeyValuePartialInformation,
  95. pKeyInfo,
  96. cbKeyInfo,
  97. &cbKeyInfo
  98. );
  99. REGCLOSEKEY( hKeySeed );
  100. if(!NT_SUCCESS(Status))
  101. return FALSE;
  102. if( pKeyInfo->DataLength > cbSeed )
  103. return FALSE;
  104. RtlCopyMemory( pbSeed, pKeyInfo->Data, pKeyInfo->DataLength );
  105. return TRUE;
  106. #endif
  107. }
  108. BOOL
  109. WriteSeed(
  110. IN PBYTE pbSeed,
  111. IN DWORD cbSeed
  112. )
  113. {
  114. HKEY hKeySeed;
  115. #ifndef KMODE_RNG
  116. LONG lRet;
  117. #else
  118. static const WCHAR wszValue[] = SEED_VALUE_NAME;
  119. UNICODE_STRING ValueName;
  120. NTSTATUS Status;
  121. PAGED_CODE();
  122. #endif // KMODE_RNG
  123. //
  124. // open handle to RNG registry key.
  125. //
  126. if(!AccessSeed( KEY_SET_VALUE, &hKeySeed ))
  127. return FALSE;
  128. #ifndef KMODE_RNG
  129. lRet = RegSetValueExA(
  130. hKeySeed,
  131. SEED_VALUE_NAME,
  132. 0,
  133. REG_BINARY,
  134. pbSeed,
  135. cbSeed
  136. );
  137. REGCLOSEKEY( hKeySeed );
  138. if( lRet != ERROR_SUCCESS )
  139. return FALSE;
  140. return TRUE;
  141. #else
  142. ValueName.Buffer = (LPWSTR)wszValue;
  143. ValueName.Length = sizeof(wszValue) - sizeof(WCHAR);
  144. ValueName.MaximumLength = sizeof(wszValue);
  145. Status = ZwSetValueKey(
  146. hKeySeed,
  147. &ValueName,
  148. 0,
  149. REG_BINARY,
  150. pbSeed,
  151. cbSeed
  152. );
  153. REGCLOSEKEY( hKeySeed );
  154. if(!NT_SUCCESS(Status))
  155. return FALSE;
  156. return TRUE;
  157. #endif
  158. }
  159. BOOL
  160. AccessSeed(
  161. IN ACCESS_MASK DesiredAccess,
  162. IN OUT PHKEY phkResult
  163. )
  164. {
  165. #ifndef KMODE_RNG
  166. DWORD dwDisposition;
  167. LONG lRet;
  168. lRet = RegCreateKeyExA(
  169. HKEY_LOCAL_MACHINE,
  170. SEED_KEY_LOCATION,
  171. 0,
  172. NULL,
  173. 0,
  174. DesiredAccess,
  175. NULL, // sa
  176. phkResult,
  177. &dwDisposition
  178. );
  179. if( lRet != ERROR_SUCCESS )
  180. return FALSE;
  181. #if 0
  182. if( dwDisposition == REG_CREATED_NEW_KEY ) {
  183. //
  184. // if we just created the seed, make sure it's Acl'd appropriately.
  185. //
  186. AdjustSeedSecurity( *phkResult );
  187. }
  188. #endif
  189. return TRUE;
  190. #else
  191. NTSTATUS Status;
  192. /// TODO at a later date: cache the registry key
  193. /// *phkResult = g_hKeySeed;
  194. /// if( *phkResult == NULL ) {
  195. UNICODE_STRING RegistryKeyName;
  196. static const WCHAR KeyLocation[] = SEED_KEY_LOCATION;
  197. ULONG Disposition;
  198. OBJECT_ATTRIBUTES ObjAttr;
  199. /// HKEY hKeyPrevious;
  200. PAGED_CODE();
  201. RegistryKeyName.Buffer = (LPWSTR)KeyLocation;
  202. RegistryKeyName.Length = sizeof(KeyLocation) - sizeof(WCHAR);
  203. RegistryKeyName.MaximumLength = sizeof(KeyLocation);
  204. InitializeObjectAttributes(
  205. &ObjAttr,
  206. &RegistryKeyName,
  207. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  208. 0,
  209. NULL
  210. );
  211. Status = ZwCreateKey(
  212. phkResult,
  213. DesiredAccess,
  214. &ObjAttr,
  215. 0,
  216. NULL,
  217. 0,
  218. &Disposition
  219. );
  220. if(!NT_SUCCESS(Status))
  221. return FALSE;
  222. /// hKeyPrevious = INTERLOCKEDCOMPAREEXCHANGEPOINTER( &g_hKeySeed, *phkResult, NULL );
  223. /// if( hKeyPrevious ) {
  224. /// REGCLOSEKEY( *phkResult );
  225. /// *phkResult = hKeyPrevious;
  226. /// }
  227. /// }
  228. return TRUE;
  229. #endif
  230. }
  231. #ifndef KMODE_RNG
  232. //
  233. // NOTE: this function should be removed if we can get the key into
  234. // the setup hives with Acl applied appropriately.
  235. //
  236. #if 0
  237. BOOL
  238. AdjustSeedSecurity(
  239. IN HKEY hKeySeed
  240. )
  241. {
  242. HKEY hKeySecurityAdjust = NULL;
  243. SID_IDENTIFIER_AUTHORITY siaWorldAuthority = SECURITY_WORLD_SID_AUTHORITY;
  244. SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
  245. SECURITY_DESCRIPTOR sd;
  246. BYTE FastBuffer[ 256 ];
  247. PACL pDacl;
  248. DWORD cbDacl;
  249. PSID psidAdministrators = NULL;
  250. PSID psidEveryone = NULL;
  251. LONG lRet;
  252. BOOL fSuccess = FALSE;
  253. //
  254. // re-open key with WRITE_DAC access and update security.
  255. // note: Wide version will fail on Win9x, which is fine, since
  256. // no security there...
  257. //
  258. lRet = RegOpenKeyExW(
  259. hKeySeed,
  260. NULL,
  261. 0,
  262. WRITE_DAC,
  263. &hKeySecurityAdjust
  264. );
  265. if( lRet != ERROR_SUCCESS )
  266. goto cleanup;
  267. if(!InitializeSecurityDescriptor( &sd, SECURITY_DESCRIPTOR_REVISION ))
  268. goto cleanup;
  269. if(!AllocateAndInitializeSid(
  270. &siaWorldAuthority,
  271. 1,
  272. SECURITY_WORLD_RID,
  273. 0, 0, 0, 0, 0, 0, 0,
  274. &psidEveryone
  275. )) {
  276. goto cleanup;
  277. }
  278. if(!AllocateAndInitializeSid(
  279. &siaNtAuthority,
  280. 2,
  281. SECURITY_BUILTIN_DOMAIN_RID,
  282. DOMAIN_ALIAS_RID_ADMINS,
  283. 0, 0, 0, 0, 0, 0,
  284. &psidAdministrators
  285. )) {
  286. goto cleanup;
  287. }
  288. cbDacl = sizeof(ACL) +
  289. 2 * ( sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) ) +
  290. GetLengthSid(psidEveryone) +
  291. GetLengthSid(psidAdministrators) ;
  292. if( cbDacl > sizeof( FastBuffer ) )
  293. goto cleanup;
  294. pDacl = (PACL)FastBuffer;
  295. if(!InitializeAcl( pDacl, cbDacl, ACL_REVISION ))
  296. goto cleanup;
  297. if(!AddAccessAllowedAce(
  298. pDacl,
  299. ACL_REVISION,
  300. KEY_QUERY_VALUE,
  301. psidEveryone
  302. )) {
  303. goto cleanup;
  304. }
  305. if(!AddAccessAllowedAce(
  306. pDacl,
  307. ACL_REVISION,
  308. KEY_ALL_ACCESS,
  309. psidAdministrators
  310. )) {
  311. goto cleanup;
  312. }
  313. if(!SetSecurityDescriptorDacl( &sd, TRUE, pDacl, FALSE ))
  314. goto cleanup;
  315. lRet = RegSetKeySecurity(
  316. hKeySecurityAdjust,
  317. DACL_SECURITY_INFORMATION,
  318. &sd
  319. );
  320. if( lRet != ERROR_SUCCESS)
  321. goto cleanup;
  322. fSuccess = TRUE;
  323. cleanup:
  324. if( hKeySecurityAdjust )
  325. REGCLOSEKEY( hKeySecurityAdjust );
  326. if( psidAdministrators )
  327. FreeSid( psidAdministrators );
  328. if( psidEveryone )
  329. FreeSid( psidEveryone );
  330. return fSuccess;
  331. }
  332. #endif
  333. #endif // !KMODE_RNG