]> gitweb.factorcode.org Git - factor.git/blob - basis/random/windows/windows.factor
72b908a32fcfefd3b3bed953080d18418ffb539e
[factor.git] / basis / random / windows / windows.factor
1 USING: accessors alien.c-types alien.data byte-arrays
2 combinators.short-circuit continuations destructors init kernel
3 locals namespaces random windows.advapi32 windows.errors
4 windows.kernel32 windows.types math.bitwise sequences fry
5 literals ;
6 IN: random.windows
7
8 TUPLE: windows-rng provider type ;
9 C: <windows-rng> windows-rng
10
11 TUPLE: windows-crypto-context handle ;
12 C: <windows-crypto-context> windows-crypto-context
13
14 M: windows-crypto-context dispose ( tuple -- )
15     handle>> 0 CryptReleaseContext win32-error=0/f ;
16
17 CONSTANT: factor-crypto-container "FactorCryptoContainer"
18
19 :: (acquire-crypto-context) ( provider type flags -- handle ret )
20     HCRYPTPROV <c-object> :> handle
21     handle
22     factor-crypto-container
23     provider
24     type
25     flags
26     CryptAcquireContextW handle swap ;
27
28 : acquire-crypto-context ( provider type -- handle )
29     CRYPT_MACHINE_KEYSET
30     (acquire-crypto-context)
31     0 = [
32         GetLastError NTE_BAD_KEYSET =
33         [ drop f ] [ win32-error-string throw ] if
34     ] [
35         *void*
36     ] if ;
37
38 : create-crypto-context ( provider type -- handle )
39     flags{ CRYPT_MACHINE_KEYSET CRYPT_NEWKEYSET }
40     (acquire-crypto-context) win32-error=0/f *void* ;
41
42 ERROR: acquire-crypto-context-failed provider type ;
43
44 : attempt-crypto-context ( provider type -- handle )
45     {
46         [ acquire-crypto-context ] 
47         [ create-crypto-context ] 
48         [ acquire-crypto-context-failed ]
49     } 2|| ;
50
51 : windows-crypto-context ( provider type -- context )
52     attempt-crypto-context <windows-crypto-context> ;
53
54 M: windows-rng random-bytes* ( n tuple -- bytes )
55     [
56         [ provider>> ] [ type>> ] bi
57         windows-crypto-context &dispose
58         handle>> swap dup <byte-array>
59         [ CryptGenRandom win32-error=0/f ] keep
60     ] with-destructors ;
61
62 ERROR: no-windows-crypto-provider error ;
63
64 : try-crypto-providers ( seq -- windows-rng )
65     [ first2 <windows-rng> ] attempt-all
66     dup windows-rng? [ no-windows-crypto-provider ] unless ;
67
68 [
69     {
70         ${ MS_ENHANCED_PROV PROV_RSA_FULL }
71         ${ MS_DEF_PROV PROV_RSA_FULL }
72     } try-crypto-providers
73     system-random-generator set-global
74
75     {
76         ${ MS_STRONG_PROV PROV_RSA_FULL }
77         ${ MS_ENH_RSA_AES_PROV PROV_RSA_AES }
78     } try-crypto-providers secure-random-generator set-global
79 ] "random.windows" add-startup-hook
80
81 [
82     [
83         ! system-random-generator get-global &dispose drop
84         ! secure-random-generator get-global &dispose drop
85     ] with-destructors
86 ] "random.windows" add-shutdown-hook