Update of /project/crypticl/cvsroot/crypticl/src In directory clnet:/tmp/cvs-serv32149
Modified Files: random.lisp Log Message: Failed attempt to get access to CryptGenRandom on Windows. Unable to get Allegro's ffi binding to do what I want.
--- /project/crypticl/cvsroot/crypticl/src/random.lisp 2007/01/24 21:45:12 1.8 +++ /project/crypticl/cvsroot/crypticl/src/random.lisp 2007/01/27 11:28:30 1.9 @@ -148,7 +148,181 @@
;;;; TESTING -(defun foo () - (setf *random-secure-state* nil) - (random-secure-bignum 128)) - \ No newline at end of file + +;;;; Failed attempt to get access to CryptGenRandom on Windows. +;;;; Unable to get Allegro's ffi binding to do what I want. +;;;(defun win32-random () ;(size) +;;; " +;;;Some material on CryptGenRandom and the win32 api in general: +;;; +;;;win32 typedefs: +;;; +;;;typedef unsigned char BYTE +;;;typedef unsigned long DWORD +;;; +;;;LPCTSTR Long Pointer to a Constant null-Terminated String (C programming/Windows API) +;;;typedef const CHAR *PCSTR, *LPCSTR; +;;; +;;;Python Cryptography Toolkit, file src/winrandom.c +;;;A successful use of CryptGenRandom. +;;; +;;;wincrypt.h +;;;typedef unsigned long HCRYPTPROV; +;;; +;;;From msdn library: +;;;http://msdn.microsoft.com/library/default.asp?url=/library/en-us/seccrypto/s... +;;; +;;;http://msdn.microsoft.com/library/default.asp?url=/library/en-us/seccrypto/s... +;;; +;;;BOOL WINAPI CryptGenRandom( +;;; HCRYPTPROV hProv, +;;; DWORD dwLen, +;;; BYTE* pbBuffer); +;;; +;;;BOOL WINAPI CryptAcquireContext( +;;; HCRYPTPROV* phProv, +;;; LPCTSTR pszContainer, +;;; LPCTSTR pszProvider, +;;; DWORD dwProvType, +;;; DWORD dwFlags); +;;; +;;;if(CryptAcquireContext( +;;; &hCryptProv, // handle to the CSP +;;; UserName, // container name +;;; NULL, // use the default provider +;;; PROV_RSA_FULL, // provider type +;;; 0)) // flag values +;;;{... +;;; +;;;Example C code: +;;; +;;;#include <windows.h> +;;;#include <wincrypt.h> +;;; +;;;static HCRYPTPROV hProvider; +;;; +;;;void spc_rand_init(void) { +;;; if (!CryptAcquireContext(&hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) +;;; ExitProcess((UINT)-1); /* Feel free to properly signal an error instead. */ +;;;} +;;; +;;;unsigned char *spc_rand(unsigned char *pbBuffer, size_t cbBuffer) { +;;; if (!hProvider) spc_rand_init( ); +;;; if (!CryptGenRandom(hProvider, cbBuffer, pbBuffer)) +;;; ExitProcess((UINT)-1); /* Feel free to properly signal an error instead. */ +;;; return pbBuffer; +;;;} +;;; +;;; +;;;Another example (from http://erngui.com/articles/rng/index.html): +;;; +;;;#define _WIN32_WINNT 0x0400 +;;;#include <windows.h> +;;;#include <wincrypt.h> +;;; +;;;long getrand() +;;;{ +;;; HCRYPTPROV hProv = 0; +;;; CryptAcquireContext(&hProv, +;;; 0, 0, PROV_RSA_FULL, +;;; CRYPT_VERIFYCONTEXT); +;;; long rnd; +;;; CryptGenRandom(hProv, +;;; sizeof(rnd), (BYTE*)&rnd); +;;; CryptReleaseContext(hProv, 0); +;;; return rnd; +;;;} +;;; +;;; +;;;/* Provider Types */ +;;;1530 #define PROV_RSA_FULL 1 +;;;1531 #define PROV_RSA_SIG 2 +;;;1532 #define PROV_DSS 3 +;;;1533 #define PROV_FORTEZZA 4 +;;;1534 #define PROV_MS_EXCHANGE 5 +;;;1535 #define PROV_SSL 6 +;;;1536 #define PROV_RSA_SCHANNEL 12 +;;;1537 #define PROV_DSS_DH 13 +;;;1538 #define PROV_EC_ECDSA_SIG 14 +;;;1539 #define PROV_EC_ECNRA_SIG 15 +;;;1540 #define PROV_EC_ECDSA_FULL 16 +;;;1541 #define PROV_EC_ECNRA_FULL 17 +;;;1542 #define PROV_DH_SCHANNEL 18 +;;;1543 #define PROV_SPYRUS_LYNKS 20 +;;;1544 #define PROV_RNG 21 +;;;1545 #define PROV_INTEL_SEC 22 +;;;1546 #define PROV_REPLACE_OWF 23 +;;;1547 #define PROV_RSA_AES 24 +;;; +;;; +;;;common error codes: +;;; +;;;ERROR_INVALID_PARAMETER ( 0x57/87L ) +;;;One of the parameters contains a value that is not valid. This is most +;;;often a pointer that is not valid. +;;; +;;;NTE_KEYSET_NOT_DEF( 0x80090019L ) +;;;The key container specified by pszContainer does not exist, or the +;;;requested provider does not exist. +;;;" +;;; (load "Kernel32.dll") ; for GetLastError +;;; (load "Advapi32.dll") +;;; ;; Check that we have the foreign functions we need +;;; (load "" :unreferenced-lib-names +;;; (list "CryptGenRandom" "CryptAcquireContextW" +;;; "CryptAcquireContextA" "GetLastError")) +;;; +;;; ;; BOOL WINAPI CryptAcquireContext( +;;; ;; HCRYPTPROV* phProv, +;;; ;; LPCTSTR pszContainer, // const CHAR *LPCTSTR ??? No? +;;; ;; LPCTSTR pszProvider, +;;; ;; DWORD dwProvType, +;;; ;; DWORD dwFlags); +;;; ;; +;;; ;; CryptAcquireContextW also seems to work. +;;; (ff:def-foreign-call (CryptAcquireContext "CryptAcquireContextA") +;;; ((phProv (* :unsigned-long) (:unsigned-long)) +;;; (pszContainer (* :char)) +;;; (pszProvider (* :char)) +;;; (dwProvType :unsigned-long fixnum) +;;; (dwFlags :unsigned-long fixnum)) +;;; :error-value :os-specific +;;; :returning (:int boolean)) +;;; +;;; (ff:def-foreign-call (GetLastError "GetLastError") (:void) +;;; :returning (:unsigned-long bignum)) +;;; +;;; (flet ((err (where) +;;; (format t "Error in ~A: 0x~,2'0X~%" where (GetLastError)))) +;;; +;;; (let ((phProv (ff:allocate-fobject :unsigned-long :foreign-static-gc))) +;;; (unless (CryptAcquireContext +;;; phProv ;phProv +;;; 0 ;pszContainer +;;; 0 ;pszProvider +;;; 1 ;dwProvType 1 = PROV_RSA_FULL +;;; 0) ;dwFlags) +;;; (err "CryptAcquireContext")) +;;; +;;; ;; BOOL WINAPI CryptGenRandom( +;;; ;; HCRYPTPROV hProv, //typedef unsigned long HCRYPTPROV; +;;; ;; DWORD dwLen, +;;; ;; BYTE* pbBuffer); //typedef unsigned char BYTE +;;; (ff:def-foreign-call (CryptGenRandom "CryptGenRandom") +;;; ((a :unsigned-long (:unsigned-long)) +;;; (b :unsigned-long) +;;; (c (* :unsigned-char))) +;;; :returning (:int boolean)) +;;; +;;; (let*((c (make-array 16 :element-type '(unsigned-byte 8) +;;; :initial-element 2)) +;;; (before (hex c)) +;;; after) +;;; ;; XXX This call always fail and error code is 87/0x57 +;;; ;; which supposedly is a bad pointer of some sort. +;;; (unless (CryptGenRandom phProv 8 c) +;;; (err "CryptGenRandom")) +;;; (setf after (hex c)) +;;; (if (string= before after) +;;; (format t "failure, no random bytes returned") +;;; (format t "SUCCESS!! Got random bytes: ~A~%" after))))))