X-Git-Url: http://www.average.org/gitweb/?p=pam_pcsc_cr.git;a=blobdiff_plain;f=gnu_crypto.c;fp=gnu_crypto.c;h=190e9e1489494dbb3eb707eafe631b467e407f31;hp=0000000000000000000000000000000000000000;hb=9cfb078547dfafdb01cfd87c05acffdbc07255ee;hpb=f105814a0f4a644d19027f92b90f2445f0366bd2 diff --git a/gnu_crypto.c b/gnu_crypto.c new file mode 100644 index 0000000..190e9e1 --- /dev/null +++ b/gnu_crypto.c @@ -0,0 +1,108 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#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, +};