change serialization interface
[pam_pcsc_cr.git] / gnu_crypto.c
1 #ifdef HAVE_CONFIG_H
2 # include "config.h"
3 #endif
4 #include <errno.h>
5 #include <gcrypt.h>
6 #include "crypto_if.h"
7
8 static const char *gnu_init(void)
9 {
10         (void)gcry_check_version(GCRYPT_VERSION);
11         gcry_control(GCRYCTL_SUSPEND_SECMEM_WARN);
12         gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
13         return "gcrypt";
14 }
15
16 static unsigned long gnu_encrypt(void *key, int keylen, void *iv,
17                         void *pt, void *ct, int tlen)
18 {
19         gcry_error_t err;
20         gcry_cipher_hd_t hd;
21
22         if ((err = gcry_cipher_open(&hd, GCRY_CIPHER_AES128,
23                                         GCRY_CIPHER_MODE_CBC, 0)))
24                 return (unsigned long)err;
25         if ((err = gcry_cipher_setkey(hd, key, keylen)))
26                 return (unsigned long)err;
27         if ((err = gcry_cipher_setiv(hd, iv, keylen)))
28                 return (unsigned long)err;
29         if ((err = gcry_cipher_encrypt(hd, ct, tlen, pt, tlen)))
30                 return (unsigned long)err;
31         if ((err = gcry_cipher_reset(hd)))
32                 return (unsigned long)err;
33         return 0UL;
34 }
35
36 static unsigned long gnu_decrypt(void *key, int keylen, void *iv,
37                         void *ct, void *pt, int tlen)
38 {
39         gcry_error_t err;
40         gcry_cipher_hd_t hd;
41
42         if ((err = gcry_cipher_open(&hd, GCRY_CIPHER_AES128,
43                                         GCRY_CIPHER_MODE_CBC, 0)))
44                 return (unsigned long)err;
45         if ((err = gcry_cipher_setkey(hd, key, keylen)))
46                 return (unsigned long)err;
47         if ((err = gcry_cipher_setiv(hd, iv, keylen)))
48                 return (unsigned long)err;
49         if ((err = gcry_cipher_decrypt(hd, pt, tlen, ct, tlen)))
50                 return (unsigned long)err;
51         if ((err = gcry_cipher_reset(hd)))
52                 return (unsigned long)err;
53         return 0UL;
54 }
55
56 static unsigned long gnu_hash(void *pt, int tlen, void *tag, int *taglen)
57 {
58         gcry_error_t err;
59         gcry_md_hd_t hd;
60
61         unsigned int dlen = gcry_md_get_algo_dlen(GCRY_MD_SHA1);
62         if (*taglen < dlen)
63                 return (unsigned long)gcry_error_from_errno(ENOMEM);
64         if ((err = gcry_md_open(&hd, GCRY_MD_SHA1, GCRY_MD_FLAG_SECURE)))
65                 return (unsigned long)err;
66         gcry_md_write(hd, pt, tlen);
67         gcry_md_final(hd);
68         memcpy(tag, gcry_md_read(hd, GCRY_MD_SHA1), dlen);
69         gcry_md_close(hd);
70         *taglen = dlen;
71         return 0UL;
72 }
73
74 static unsigned long gnu_hmac(void *key, int keylen, void *pt, int tlen,
75                         void *tag, int *taglen)
76 {
77         gcry_error_t err;
78         gcry_md_hd_t hd;
79
80         unsigned int dlen = gcry_md_get_algo_dlen(GCRY_MD_SHA1);
81         if (*taglen < dlen)
82                 return (unsigned long)gcry_error_from_errno(ENOMEM);
83         if ((err = gcry_md_open(&hd, GCRY_MD_SHA1, GCRY_MD_FLAG_SECURE |
84                                                         GCRY_MD_FLAG_HMAC)))
85                 return (unsigned long)err;
86         if ((err = gcry_md_setkey(hd, key, keylen)))
87                 return (unsigned long)err;
88         gcry_md_write(hd, pt, tlen);
89         gcry_md_final(hd);
90         memcpy(tag, gcry_md_read(hd, GCRY_MD_SHA1), dlen);
91         gcry_md_close(hd);
92         *taglen = dlen;
93         return 0UL;
94 }
95
96 static const char *gnu_errstr(unsigned long err)
97 {
98         return gcry_strerror((gcry_error_t)err);
99 }
100
101 struct crypto_interface gnu_crypto_if = {
102         .init           = gnu_init,
103         .encrypt        = gnu_encrypt,
104         .decrypt        = gnu_decrypt,
105         .hash           = gnu_hash,
106         .hmac           = gnu_hmac,
107         .errstr         = gnu_errstr,
108 };