]> www.average.org Git - pam_pcsc_cr.git/blobdiff - gnu_crypto.c
support gcrypt library
[pam_pcsc_cr.git] / gnu_crypto.c
diff --git a/gnu_crypto.c b/gnu_crypto.c
new file mode 100644 (file)
index 0000000..190e9e1
--- /dev/null
@@ -0,0 +1,108 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <errno.h>
+#include <gcrypt.h>
+#include "crypto_if.h"
+
+static const char *gnu_init(void)
+{
+       (void)gcry_check_version(GCRYPT_VERSION);
+       gcry_control(GCRYCTL_SUSPEND_SECMEM_WARN);
+       gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
+       return "gcrypt";
+}
+
+static unsigned long gnu_encrypt(void *key, int keylen, void *iv,
+                       void *pt, void *ct, int tlen)
+{
+       gcry_error_t err;
+       gcry_cipher_hd_t hd;
+
+       if ((err = gcry_cipher_open(&hd, GCRY_CIPHER_AES128,
+                                       GCRY_CIPHER_MODE_CBC, 0)))
+               return (unsigned long)err;
+       if ((err = gcry_cipher_setkey(hd, key, keylen)))
+               return (unsigned long)err;
+       if ((err = gcry_cipher_setiv(hd, iv, keylen)))
+               return (unsigned long)err;
+       if ((err = gcry_cipher_encrypt(hd, ct, tlen, pt, tlen)))
+               return (unsigned long)err;
+       if ((err = gcry_cipher_reset(hd)))
+               return (unsigned long)err;
+       return 0UL;
+}
+
+static unsigned long gnu_decrypt(void *key, int keylen, void *iv,
+                       void *ct, void *pt, int tlen)
+{
+       gcry_error_t err;
+       gcry_cipher_hd_t hd;
+
+       if ((err = gcry_cipher_open(&hd, GCRY_CIPHER_AES128,
+                                       GCRY_CIPHER_MODE_CBC, 0)))
+               return (unsigned long)err;
+       if ((err = gcry_cipher_setkey(hd, key, keylen)))
+               return (unsigned long)err;
+       if ((err = gcry_cipher_setiv(hd, iv, keylen)))
+               return (unsigned long)err;
+       if ((err = gcry_cipher_decrypt(hd, pt, tlen, ct, tlen)))
+               return (unsigned long)err;
+       if ((err = gcry_cipher_reset(hd)))
+               return (unsigned long)err;
+       return 0UL;
+}
+
+static unsigned long gnu_hash(void *pt, int tlen, void *tag, int *taglen)
+{
+       gcry_error_t err;
+       gcry_md_hd_t hd;
+
+       unsigned int dlen = gcry_md_get_algo_dlen(GCRY_MD_SHA1);
+       if (*taglen < dlen)
+               return (unsigned long)gcry_error_from_errno(ENOMEM);
+       if ((err = gcry_md_open(&hd, GCRY_MD_SHA1, GCRY_MD_FLAG_SECURE)))
+               return (unsigned long)err;
+       gcry_md_write(hd, pt, tlen);
+       gcry_md_final(hd);
+       memcpy(tag, gcry_md_read(hd, GCRY_MD_SHA1), dlen);
+       gcry_md_close(hd);
+       *taglen = dlen;
+       return 0UL;
+}
+
+static unsigned long gnu_hmac(void *key, int keylen, void *pt, int tlen,
+                       void *tag, int *taglen)
+{
+       gcry_error_t err;
+       gcry_md_hd_t hd;
+
+       unsigned int dlen = gcry_md_get_algo_dlen(GCRY_MD_SHA1);
+       if (*taglen < dlen)
+               return (unsigned long)gcry_error_from_errno(ENOMEM);
+       if ((err = gcry_md_open(&hd, GCRY_MD_SHA1, GCRY_MD_FLAG_SECURE |
+                                                       GCRY_MD_FLAG_HMAC)))
+               return (unsigned long)err;
+       if ((err = gcry_md_setkey(hd, key, keylen)))
+               return (unsigned long)err;
+       gcry_md_write(hd, pt, tlen);
+       gcry_md_final(hd);
+       memcpy(tag, gcry_md_read(hd, GCRY_MD_SHA1), dlen);
+       gcry_md_close(hd);
+       *taglen = dlen;
+       return 0UL;
+}
+
+static const char *gnu_errstr(unsigned long err)
+{
+       return gcry_strerror((gcry_error_t)err);
+}
+
+struct crypto_interface gnu_crypto_if = {
+       .init           = gnu_init,
+       .encrypt        = gnu_encrypt,
+       .decrypt        = gnu_decrypt,
+       .hash           = gnu_hash,
+       .hmac           = gnu_hmac,
+       .errstr         = gnu_errstr,
+};