hmac-sha1.ss
(module hmac-sha1 mzscheme
  (require (lib "foreign.ss")
           (all-except (lib "contract.ss")
                       ->)
           (rename (lib "contract.ss")
                   c-> ->))
  (unsafe!)
  
  (define openssl-crypto
    (case (system-type)
      [(windows)
       (ffi-lib "libeay32")]
      [else
       (ffi-lib "libcrypto")]))
  
  (define EVP_SHA1
    (get-ffi-obj 'EVP_sha1 openssl-crypto
                 (_fun -> _fpointer)))
  
  (define HMAC-SHA1/raw
    (get-ffi-obj 'HMAC openssl-crypto
                 (_fun [EVP_MD : _fpointer = (EVP_SHA1)]
                       [key : _bytes]
                       [key_len : _int = (bytes-length key)]
                       [data : _bytes]
                       [data_len : _int = (bytes-length data)]
                       [md : _int = 0]
                       [md_len : _int = 0]
                       ->
                       _pointer)))
  
  (define (HMAC-SHA1 key data)
    ; It returns the same pointer always
    (bytes-copy
     ; A SHA1 is 20 bytes, including 0s
     (make-sized-byte-string (HMAC-SHA1/raw key data) 20)))
  
  (provide/contract
   [HMAC-SHA1 (bytes? bytes? . c-> . bytes?)]))